Класс QWaitCondition
Класс QWaitCondition предоставляет переменную условия для синхронизации потоков. Подробнее...
| Заголовок: | #include <QWaitCondition> |
| qmake: | QT += core |
Примечание: Все функции в этом классе являются потокобезопасными.
Открытые функции
| QWaitCondition() | |
| ~QWaitCondition() | |
| void | notify_all() |
| void | notify_one() |
| bool | wait(QMutex *lockedMutex, unsigned long time = ULONG_MAX) |
| bool | wait(QReadWriteLock *lockedReadWriteLock, unsigned long time = ULONG_MAX) |
| void | wakeAll() |
| void | wakeOne() |
Подробное описание
QWaitCondition позволяет одному потоку сообщить другим потокам, что какое-то условие выполнено. Один или несколько потоков могут блокироваться в ожидании, пока QWaitCondition не установит условие с помощью wakeOne() или wakeAll(). Используйте wakeOne(), чтобы разбудить случайный выбранный поток, или wakeAll(), чтобы разбудить их всех.
Например, предположим, что у нас есть три задачи, которые должны выполняться всякий раз, когда пользователь нажимает клавишу. Каждая задача может быть разделена на поток, каждый из которых будет иметь тело run() вот так:
forever {
mutex.lock();
keyPressed.wait(&mutex);
do_something();
mutex.unlock();
} Здесь переменная keyPressed является глобальной переменной типа QWaitCondition.
Четвертый поток будет считывать нажатия клавиш и разбуживать другие три потока каждый раз, когда он получает одно, примерно так:
forever {
getchar();
keyPressed.wakeAll();
} Порядок, в котором три потока будут разбужены, не определён. Кроме того, если некоторые из потоков всё ещё в do_something() при нажатии клавиши, они не будут разбужены (поскольку они не ждут переменной условия), и поэтому задача не будет выполнена для этого нажатия клавиши. Эту проблему можно решить, используя счётчик и QMutex для его защиты. Например, вот новый код для потоков-работников:
forever {
mutex.lock();
keyPressed.wait(&mutex);
++count;
mutex.unlock();
do_something();
mutex.lock();
--count;
mutex.unlock();
} Вот код для четвёртого потока:
forever {
getchar();
mutex.lock();
// Sleep until there are no busy worker threads
while (count > 0) {
mutex.unlock();
sleep(1);
mutex.lock();
}
keyPressed.wakeAll();
mutex.unlock();
} Мьютекс необходим, потому что результаты попыток двух потоков одновременного изменения значения одной и той же переменной непредсказуемы.
Переменные условий — мощный инструмент синхронизации потоков. Пример Wait Conditions Example показывает, как использовать QWaitCondition в качестве альтернативы QSemaphore для управления доступом к кольцевому буферу, совместно используемому производителем и потребителем потоков.
См. также QMutex, QSemaphore, QThread и Wait Conditions Example.
Документация по функциям-членам
QWaitCondition::QWaitCondition()
Создаёт новый объект условия ожидания.
QWaitCondition::~QWaitCondition()
Удаляет объект условия ожидания.
void QWaitCondition::notify_all()
Эта функция предоставляется для совместимости со STL. Она эквивалентна wakeAll().
Эта функция была добавлена в Qt 5.8.
void QWaitCondition::notify_one()
Эта функция предоставляется для совместимости со STL. Она эквивалентна wakeOne().
Эта функция была добавлена в Qt 5.8.
bool QWaitCondition::wait(QMutex *lockedMutex, unsigned long time = ULONG_MAX)
Освобождает мьютекс lockedMutex и ожидает выполнения условия ожидания. Мьютекс lockedMutex должен быть заблокирован вызывающей нитью. Если lockedMutex не находится в заблокированном состоянии, поведение не определено. Если lockedMutex — рекурсивный мьютекс, эта функция возвращает значение немедленно. Мьютекс lockedMutex будет разблокирован, и вызывающая нить будет блокироваться до тех пор, пока не будет выполнено одно из следующих условий:
- Другая нить сигнализирует об этом, используя wakeOne() или wakeAll(). В этом случае функция вернет true.
-
Прошло time миллисекунд. Если time равно
ULONG_MAX(значение по умолчанию), ожидание никогда не истечёт (событие должно быть сигнализировано). Если ожидание истекло, функция вернет false.
Мьютекс lockedMutex будет возвращён в то же заблокированное состояние. Эта функция предназначена для атомарного перехода из заблокированного состояния в состояние ожидания.
См. также wakeOne() и wakeAll().
bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, unsigned long time = ULONG_MAX)
Освобождает блокировку lockedReadWriteLock и ожидает выполнения условия ожидания. Блокировка lockedReadWriteLock должна быть заблокирована вызывающей нитью. Если lockedReadWriteLock не находится в заблокированном состоянии, функция возвращается немедленно. lockedReadWriteLock не должен быть заблокирован рекурсивно, иначе функция не разблокирует его должным образом. Блокировка lockedReadWriteLock будет разблокирована, и вызывающая нить будет блокироваться до тех пор, пока не будет выполнено одно из следующих условий:
- Другая нить сигнализирует об этом, используя wakeOne() или wakeAll(). В этом случае функция вернет true.
-
Прошло time миллисекунд. Если time равно
ULONG_MAX(значение по умолчанию), ожидание никогда не истечёт (событие должно быть сигнализировано). Если ожидание истекло, функция вернет false.
Блокировка lockedReadWriteLock будет возвращена в то же заблокированное состояние. Эта функция предназначена для атомарного перехода из заблокированного состояния в состояние ожидания.
Эта функция была добавлена в Qt 4.4.
См. также wakeOne() и wakeAll().
void QWaitCondition::wakeAll()
Разбуживает все нити, ожидающие выполнения условия ожидания. Порядок разбужения нитей зависит от политик планирования операционной системы и не может быть контролируем или предсказан.
См. также wakeOne().
void QWaitCondition::wakeOne()
Разбуживает одну нить, ожидающую выполнения условия ожидания. Нить, которая будет разбужена, зависит от политик планирования операционной системы и не может быть контролируема или предсказана.
Если вы хотите разбудить определённую нить, обычно следует использовать различные условия ожидания и заставлять разные нити ожидать разных условий.
См. также wakeAll().
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.14/qwaitcondition.html