Spec-Zone.ru › Qt 6.0

Класс 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.0/qwaitcondition.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API