Класс QWaitCondition
Класс QWaitCondition предоставляет переменную условия для синхронизации потоков. Подробнее...
| Заголовок: | #include <QWaitCondition> |
| qmake: | QT += core |
Примечание: Все функции в этом классе являются безопасными для потоков.
Открытые функции
| QWaitCondition() | |
| ~QWaitCondition() | |
| void | notify_all() |
| void | notify_one() |
| bool | wait(QMutex *lockedMutex, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)) |
| bool | wait(QMutex *lockedMutex, unsigned long time) |
| bool | wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever)) |
| bool | wait(QReadWriteLock *lockedReadWriteLock, unsigned long time) |
| 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, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
Освобождает lockedMutex и ожидает переменной условия. lockedMutex должен быть изначально заблокирован вызывающим потоком. Если lockedMutex не заблокирован, поведение не определено. Если lockedMutex — рекурсивный мьютекс, эта функция возвращается немедленно. lockedMutex будет разблокирован, и вызывающий поток будет блокироваться, пока не выполнится одно из этих условий:
- Другой поток сигнализирует ему с помощью wakeOne() или wakeAll(). В этом случае функция вернёт true.
- достигнет дедлайна, заданного deadline. Если deadline равен
QDeadlineTimer::Forever(по умолчанию), ожидание никогда не истечёт (событие должно быть сигнализировано). Если ожидание истечёт, функция вернёт false.
lockedMutex будет возвращён в то же заблокированное состояние. Эта функция предназначена для атомарного перехода от заблокированного состояния к состоянию ожидания.
Эта функция была добавлена в Qt 5.12.
См. также wakeOne() и wakeAll().
bool QWaitCondition::wait(QMutex *lockedMutex, unsigned long time)
Это перегруженная функция.
bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))
Освобождает lockedReadWriteLock и ожидает переменной условия. lockedReadWriteLock должен быть изначально заблокирован вызывающим потоком. Если lockedReadWriteLock не заблокирован, функция возвращается немедленно. lockedReadWriteLock не должен блокироваться рекурсивно, иначе функция не разблокирует его должным образом. lockedReadWriteLock будет разблокирован, и вызывающий поток будет блокироваться, пока не выполнится одно из этих условий:
- Другой поток сигнализирует ему с помощью wakeOne() или wakeAll(). В этом случае функция вернёт true.
- достигнет дедлайна, заданного deadline. Если deadline равно
QDeadlineTimer::Forever(по умолчанию), ожидание никогда не истечёт (событие должно быть сигнализировано). Если ожидание истечёт, функция вернёт false.
lockedReadWriteLock будет возвращён в то же заблокированное состояние. Эта функция предназначена для атомарного перехода от заблокированного состояния к состоянию ожидания.
Эта функция была добавлена в Qt 5.12.
См. также wakeOne() и wakeAll().
bool QWaitCondition::wait(QReadWriteLock *lockedReadWriteLock, unsigned long time)
Это перегруженная функция.
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.15/qwaitcondition.html