Files
pip/libs/main/thread/piconditionvar.h
2026-03-20 16:31:30 +03:00

178 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! \~\file piconditionvar.h
//! \~\ingroup Thread
//! \~\brief
//! \~english Condition variable for waiting and notification between threads
//! \~russian Переменная условия для ожидания и уведомления между потоками
/*
PIP - Platform Independent Primitives
Condition variable for waiting and notification between threads
Stephan Fomenko
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PICONDITIONVAR_H
#define PICONDITIONVAR_H
#include "pimutex.h"
#include "pisystemtime.h"
//! \~\ingroup Thread
//! \~\brief
//! \~english Condition variable used together with external %PIMutex.
//! \~russian Переменная условия, используемая вместе с внешним %PIMutex.
class PIP_EXPORT PIConditionVariable {
public:
NO_COPY_CLASS(PIConditionVariable);
//! \~english Constructs condition variable.
//! \~russian Создает переменную условия.
explicit PIConditionVariable();
//! \~english Destroys condition variable.
//! \~russian Уничтожает переменную условия.
virtual ~PIConditionVariable();
//! \~english Wakes one waiting thread, if any.
//! \~russian Пробуждает один ожидающий поток, если он есть.
void notifyOne();
//! \~english Wakes all threads currently waiting on this variable.
//! \~russian Пробуждает все потоки, ожидающие на этой переменной.
void notifyAll();
//! \~english Waits until notification, temporarily releasing \a lk while blocked.
//! \~russian Ожидает уведомления, временно освобождая \a lk на время блокировки.
virtual void wait(PIMutex & lk);
//! \~\brief
//! \~english Waits until \a condition becomes true, rechecking it after each wakeup while \a lk is locked.
//! \~russian Ожидает, пока \a condition не станет истинным, повторно проверяя его после каждого пробуждения при заблокированном \a lk.
//! \~\details
//! \~english
//! The execution of the current thread (which shall have locked with lk method PIMutex::lock()) is blocked
//! until notified.
//!
//! At the moment of blocking the thread, the function automatically calls lk.unlock() (PIMutex::unlock()),
//! allowing other locked threads to continue.
//!
//! Once notified (explicitly, by some other thread), the function unblocks and calls lk.lock() (PIMutex::lock()),
//! leaving lk in the same state as when the function was called. Then the function returns (notice that this last mutex
//! locking may block again the thread before returning).
//!
//! Generally, the function is notified to wake up by a call in another thread either to member notifyOne() or to
//! member notifyAll(). But certain implementations may produce spurious wake-up calls without any of these functions
//! being called. Therefore, users of this function shall ensure their condition for resumption is met.
//!
//! If condition is specified, the function only blocks if condition returns false, and notifications can only unblock
//! the thread when it becomes true (which is specially useful to check against spurious wake-up calls).
//!
//! \param lk lock object used by method wait for data protection
//! \param condition A callable object or function that takes no arguments and returns a value that can be evaluated
//! as a bool. This is called repeatedly until it evaluates to true.
//!
//! \~russian
//! Выполнение текущего потока (который должен быть заблокирован с помощью \a lk методом PIMutex::lock())
//! приостанавливается до получения уведомления.
//!
//! В момент блокировки потока функция автоматически вызывает lk.unlock() (PIMutex::unlock()),
//! позволяя другим заблокированным потокам продолжить выполнение.
//!
//! После получения уведомления (явного, от другого потока) функция разблокируется и вызывает
//! lk.lock() (PIMutex::lock()), возвращая lk в то же состояние, в котором он находился при вызове
//! функции. Затем функция завершается (обратите внимание, что эта последняя блокировка мьютекса
//! может снова заблокировать поток перед возвратом).
//!
//! Обычно функция пробуждается при вызове в другом потоке либо notifyOne(), либо notifyAll().
//! Однако некоторые реализации могут создавать ложные пробуждения без вызова любой из этих функций.
//! Поэтому пользователи этой функции должны убедиться, что условие для возобновления выполнено.
//!
//! Если указано condition, функция блокируется только если condition возвращает false,
//! а уведомления могут разблокировать поток только когда оно станет true (что особенно полезно
//! для проверки ложных пробуждений).
//!
//! \param lk объект блокировки, используемый методом wait для защиты данных
//! \param condition вызываемый объект или функция, не принимающая аргументов и возвращающая значение, которое может быть оценено как
//! bool. Вызывается повторно, пока не примет значение true
//!
virtual void wait(PIMutex & lk, std::function<bool ()> condition);
//! \~english Waits for at most \a timeout and returns \c true if awakened before it expires.
//! \~russian Ожидает не дольше \a timeout и возвращает \c true, если пробуждение произошло до его истечения.
virtual bool waitFor(PIMutex & lk, PISystemTime timeout);
//! \brief
//! \~english Waits until \a condition becomes true or \a timeout expires.
//! \~russian Ожидает, пока \a condition не станет истинным или не истечет \a timeout.
//! \~\details
//! \~english
//! The execution of the current thread (which shall have locked with lk method PIMutex::lock()) is blocked
//! during timeout, or until notified (if the latter happens first).
//!
//! At the moment of blocking the thread, the function automatically calls lk.lock() (PIMutex::lock()), allowing
//! other locked threads to continue.
//!
//! Once notified or once timeout has passed, the function unblocks and calls lk.unlock() (PIMutex::unlock()),
//! leaving lk in the same state as when the function was called. Then the function returns (notice that this last
//! mutex locking may block again the thread before returning).
//!
//! Generally, the function is notified to wake up by a call in another thread either to member notifyOne() or to
//! member notifyAll(). But certain implementations may produce spurious wake-up calls without any of these functions
//! being called. Therefore, users of this function shall ensure their condition for resumption is met.
//!
//! If condition is specified, the function only blocks if condition returns false, and notifications can only unblock
//! the thread when it becomes true (which is especially useful to check against spurious wake-up calls).
//!
//! \param lk lock object used by method wait for data protection
//! \param condition A callable object or function that takes no arguments and returns a value that can be evaluated
//! as a bool. This is called repeatedly until it evaluates to true.
//! \return false if timeout reached or true if wakeup condition is true
//!
//! \~russian
//! Выполнение текущего потока (который должен быть заблокирован с помощью lk методом PIMutex::lock())
//! приостанавливается на время timeout, или до получения уведомления (в зависимости от того,
//! что произойдет раньше).
//!
//! В момент блокировки потока функция автоматически вызывает lk.unlock() (PIMutex::unlock()),
//! позволяя другим заблокированным потокам продолжить выполнение.
//!
//! После получения уведомления или истечения таймаута функция разблокируется и вызывает
//! lk.lock() (PIMutex::lock()), возвращая lk в то же состояние, в котором он находился при вызове
//! функции. Затем функция завершается (обратите внимание, что эта последняя блокировка мьютекса
//! может снова заблокировать поток перед возвратом).
//!
//! Обычно функция пробуждается при вызове в другом потоке либо notifyOne(), либо notifyAll().
//! Однако некоторые реализации могут создавать ложные пробуждения без вызова любой из этих функций.
//! Поэтому пользователи этой функции должны убедиться, что условие для возобновления выполнено.
//!
//! Если указано condition, функция блокируется только если condition возвращает false,
//! а уведомления могут разблокировать поток только когда оно станет true (что особенно полезно
//! для проверки ложных пробуждений).
//!
//! \param lk объект блокировки, используемый методом wait для защиты данных
//! \param timeout время ожидания
//! \param condition вызываемый объект или функция, не принимающая аргументов и возвращающая значение, которое может быть оценено как
//! bool. Вызывается повторно, пока не примет значение true
//! \return false если достигнут таймаут, или true если условие пробуждения истинно
//!
virtual bool waitFor(PIMutex & lk, PISystemTime timeout, std::function<bool()> condition);
private:
PRIVATE_DECLARATION(PIP_EXPORT)
};
#endif // PICONDITIONVAR_H