Класс QWaitCondition
Класс QWaitCondition предоставляет переменную условия для синхронизации потоков. Подробнее...
| Заголовок: | #include <QWaitCondition> |
| CMake: | find_package(Qt6 COMPONENTS Core REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Core) |
| 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()
Удаляет объект переменной условия.
[since 5.8] void QWaitCondition::notify_all()
Эта функция предоставляется для совместимости со STL. Она эквивалентна wakeAll().
Эта функция была добавлена в Qt 5.8.
[since 5.8] void QWaitCondition::notify_one()
Эта функция предоставляется для совместимости со STL. Она эквивалентна wakeOne().
Эта функция была добавлена в Qt 5.8.
[since 5.12] 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)
Это перегруженная функция.
[since 5.12] 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-6.2/qwaitcondition.html