C++/標準ライブラリ/condition variable
表示
33.7 Condition variables (thread.condition)
[編集]33.7.1 General (thread.condition.general)
[編集]- 概要
- Condition variablesは、あるスレッドが他のスレッドによって条件が満たされるか、システム時間に達するまでブロックされるための同期プリミティブを提供します。
condition_variable
クラスは、unique_lock<mutex>
型のオブジェクト上でのみ待機できるcondition variableを提供し、実装を効率化します。condition_variable_any
クラスは、ユーザーが提供する任意のロック型のオブジェクト上で待機できる一般的なcondition variableを提供します。
- Condition variablesは、あるスレッドが他のスレッドによって条件が満たされるか、システム時間に達するまでブロックされるための同期プリミティブを提供します。
- 同時呼び出しの許可
- Condition variablesは、
wait
、wait_for
、wait_until
、notify_one
、notify_all
メンバー関数の同時呼び出しを許可します。
- Condition variablesは、
- 関数の原子性
notify_one
とnotify_all
の実行は原子操作です。wait
、wait_for
、wait_until
の実行は次の3つの原子部分で行われます:
- ミューテックスの解放と待機状態への移行
- 待機の解除
- ロックの再取得
- 全順序の保持
- 実装は、
notify_one
、notify_all
のすべての実行およびwait
、wait_for
、wait_until
の各部分が、「前に起こる」順序と一致する単一の未定義の全順序で実行されるように振る舞います。
- 実装は、
- コンストラクションとデストラクション
- Condition variableの構築と破棄は同期化を必要としません。
33.7.2 Header <condition_variable> synopsis (condition.variable.syn)
[編集]namespace std { // 33.7.4, class condition_variable class condition_variable; // 33.7.5, class condition_variable_any class condition_variable_any; // 33.7.3, non-member functions void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk); enum class cv_status { no_timeout, timeout }; }
33.7.3 Non-member functions (thread.condition.nonmember)
[編集]void notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk);
- 前提条件
lk
は呼び出しスレッドによってロックされており、以下のいずれかを満たしていること:
- 他のスレッドが
cond
を待っていない lk.mutex()
が、同時に待機しているスレッドすべてに対して同じ値を返す
- 効果
lk
に関連付けられたロックの所有権を内部ストレージに移し、現在のスレッドが終了したときにcond
を通知するようにスケジュールします。この通知は以下と同等です:lk.unlock(); cond.notify_all();
- 同期化
- 暗黙の
lk.unlock()
呼び出しは、現在のスレッドに関連するすべてのスレッドストレージ期間のオブジェクトが破壊された後に順序付けられます。
- 暗黙の
- 注記
- 供給されたロックはスレッドが終了するまで保持されるため、ロックの順序に起因するデッドロックを引き起こす可能性があります。
- ユーザーは、スプリアスウェイクアップを経験した場合に待機しているスレッドが誤ってスレッドが終了したと仮定しないようにする責任があります。
33.7.4 Class condition_variable (thread.condition.condvar)
[編集]namespace std { class condition_variable { public: condition_variable(); ~condition_variable(); condition_variable(const condition_variable&) = delete; condition_variable& operator=(const condition_variable&) = delete; void notify_one() noexcept; void notify_all() noexcept; void wait(unique_lock<mutex>& lock); template<class Predicate> void wait(unique_lock<mutex>& lock, Predicate pred); template<class Clock, class Duration> cv_status wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time); template<class Clock, class Duration, class Predicate> bool wait_until(unique_lock<mutex>& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); template<class Rep, class Period> cv_status wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time); template<class Rep, class Period, class Predicate> bool wait_for(unique_lock<mutex>& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred); using native_handle_type = implementation-defined; native_handle_type native_handle(); }; }
- クラスの概要
condition_variable
は標準レイアウトクラスです。
- コンストラクタ
- 例外が必要な場合、
system_error
をスローします。
- 例外が必要な場合、
- エラー条件
resource_unavailable_try_again
— 初期化を妨げる非メモリリソース制限がある場合。
- デストラクタの前提条件
- このcondition variable上でブロックされているスレッドがないこと。
notify_one
- このcondition variableを待機しているスレッドがある場合、そのうちの1つを解除します。
notify_all
- このcondition variableを待機しているすべてのスレッドを解除します。
wait
- 前提条件:
lock.owns_lock()
がtrueであり、呼び出しスレッドによってlock.mutex()
がロックされている。 - 効果:
lock.unlock()
を原子的に呼び出し、*this
でブロックします。ブロックが解除されると、lock.lock()
を呼び出します。 - 後条件:
lock.owns_lock()
がtrueであり、lock.mutex()
が呼び出しスレッドによってロックされている。 - 例外: 何もスローしない。
- 前提条件:
wait
(プレディケート付き)- 前提条件:
lock.owns_lock()
がtrueであり、呼び出しスレッドによってlock.mutex()
がロックされている。 - 効果: プレディケートが満たされるまで待機します。
- 後条件:
lock.owns_lock()
がtrueであり、lock.mutex()
が呼び出しスレッドによってロックされている。 - 例外:
pred
によってスローされた任意の例外。
- 前提条件:
wait_until
- 前提条件:
lock.owns_lock()
がtrueであり、呼び出しスレッドによってlock.mutex()
がロックされている。 - 効果:
abs_time
に達するまで待機します。 - 後条件:
lock.owns_lock()
がtrueであり、lock.mutex()
が呼び出しスレッドによってロックされている。 - 戻り値:
cv_status::timeout
(タイムアウトした場合)、それ以外はcv_status::no_timeout
。 - 例外: タイムアウト関連の例外。
- 前提条件:
wait_for
- 前提条件:
lock.owns_lock()
がtrueであり、呼び出しスレッドによってlock.mutex()
がロックされている。 - 効果: 指定された相対時間
rel_time
が経過するまで待機します。 - 後条件:
lock.owns_lock()
がtrueであり、lock.mutex()
が呼び出しスレッドによってロックされている。 - 戻り値:
cv_status::timeout
(タイムアウトした場合)、それ以外はcv_status::no_timeout
。 - 例外: タイムアウト関連の例外。
- 前提条件:
wait_until
(プレディケート付き)- 前提条件:
lock.owns_lock()
がtrueであり、呼び出しスレッドによってlock.mutex()
がロックされている。 - 効果: プレディケートが満たされるか、
abs_time
に達するまで待機します。 - 後条件:
lock.owns_lock()
がtrueであり、lock.mutex()
が呼び出しスレッドによってロックされている。 - 戻り値:
pred
がtrueを返した場合はtrue、それ以外はfalse。 - 例外:
pred
によってスローされた任意の例外。
- 前提条件:
wait_for
(プレディケート付き)- 前提条件:
lock.owns_lock()
がtrueであり、呼び出しスレッドによってlock.mutex()
がロックされている。 - 効果: プレディケートが満たされるか、指定された相対時間
rel_time
が経過するまで待機します。 - 後条件:
lock.owns_lock()
がtrueであり、lock.mutex()
が呼び出しスレッドによってロックされている。 - 戻り値:
pred
がtrueを返した場合はtrue、それ以外はfalse。 - 例外:
pred
によってスローされた任意の例外。
- 前提条件:
native_handle
- 戻り値: 内部の実装定義のネイティブハンドルを返します。
33.7.5 Class condition_variable_any (thread.condition.condvarany)
[編集]namespace std { class condition_variable_any { public: condition_variable_any(); ~condition_variable_any(); condition_variable_any(const condition_variable_any&) = delete; condition_variable_any& operator=(const condition_variable_any&) = delete; void notify_one() noexcept; void notify_all() noexcept; template <class Lock> void wait(Lock& lock); template <class Lock, class Predicate> void wait(Lock& lock, Predicate pred); template <class Lock, class Clock, class Duration> cv_status wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time); template <class Lock, class Clock, class Duration, class Predicate> bool wait_until(Lock& lock, const chrono::time_point<Clock, Duration>& abs_time, Predicate pred); template <class Lock, class Rep, class Period> cv_status wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time); template <class Lock, class Rep, class Period, class Predicate> bool wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time, Predicate pred); using native_handle_type = implementation-defined; native_handle_type native_handle(); }; }
- クラスの概要
condition_variable_any
は標準レイアウトクラスです。
- コンストラクタ
- 例外が必要な場合、
system_error
をスローします。
- 例外が必要な場合、
- エラー条件
resource_unavailable_try_again
— 初期化を妨げる非メモリリソース制限がある場合。
- デストラクタの前提条件
- このcondition variable上でブロックされているスレッドがないこと。
notify_one
- このcondition variableを待機しているスレッドがある場合、そのうちの1つを解除します。
notify_all
- このcondition variableを待機しているすべてのスレッドを解除します。
wait
- 前提条件:
lock
は呼び出しスレッドによってロックされている。 - 効果:
lock.unlock()
を原子的に呼び出し、*this
でブロックします。ブロックが解除されると、lock.lock()
を呼び出します。 - 後条件:
lock
は呼び出しスレッドによってロックされている。 - 例外: 何もスローしない。
- 前提条件:
wait
(プレディケート付き)- 前提条件:
lock
は呼び出しスレッドによってロックされている。 - 効果: プレディケートが満たされるまで待機します。
- 後条件:
lock
は呼び出しスレッドによってロックされている。 - 例外:
pred
によってスローされた任意の例外。
- 前提条件:
wait_until
- 前提条件:
lock
は呼び出しスレッドによってロックされている。 - 効果:
abs_time
に達するまで待機します。 - 後条件:
lock
は呼び出しスレッドによってロックされている。 - 戻り値:
cv_status::timeout
(タイムアウトした場合)、それ以外はcv_status::no_timeout
。 - 例外: タイムアウト関連の例外。
- 前提条件:
wait_for
- 前提条件:
lock
は呼び出しスレッドによってロックされている。 - 効果: 指定された相対時間
rel_time
が経過するまで待機します。 - 後条件:
lock
は呼び出しスレッドによってロックされている。 - 戻り値:
cv_status::timeout
(タイムアウトした場合)、それ以外はcv_status::no_timeout
。
- 例外:タイムアウト関連の例外。
- 前提条件:
wait_until
(プレディケート付き)- 前提条件:
lock
は呼び出しスレッドによってロックされている。 - 効果: プレディケートが満たされるか、
abs_time
に達するまで待機します。 - 後条件:
lock
は呼び出しスレッドによってロックされている。 - 戻り値:
pred
がtrueを返した場合はtrue、それ以外はfalse。 - 例外:
pred
によってスローされた任意の例外。
- 前提条件:
wait_for
(プレディケート付き)- 前提条件:
lock
は呼び出しスレッドによってロックされている。 - 効果: プレディケートが満たされるか、指定された相対時間
rel_time
が経過するまで待機します。 - 後条件:
lock
は呼び出しスレッドによってロックされている。 - 戻り値:
pred
がtrueを返した場合はtrue、それ以外はfalse。 - 例外:
pred
によってスローされた任意の例外。
- 前提条件:
native_handle
- 戻り値: 内部の実装定義のネイティブハンドルを返します。