コンテンツにスキップ

C++/標準ライブラリ/condition variable

出典: フリー教科書『ウィキブックス(Wikibooks)』

33.7 Condition variables (thread.condition)[編集]

33.7.1 General (thread.condition.general)[編集]

  1. 概要
    Condition variablesは、あるスレッドが他のスレッドによって条件が満たされるか、システム時間に達するまでブロックされるための同期プリミティブを提供します。condition_variableクラスは、unique_lock<mutex>型のオブジェクト上でのみ待機できるcondition variableを提供し、実装を効率化します。condition_variable_anyクラスは、ユーザーが提供する任意のロック型のオブジェクト上で待機できる一般的なcondition variableを提供します。
  2. 同時呼び出しの許可
    Condition variablesは、waitwait_forwait_untilnotify_onenotify_allメンバー関数の同時呼び出しを許可します。
  3. 関数の原子性
    notify_onenotify_allの実行は原子操作です。waitwait_forwait_untilの実行は次の3つの原子部分で行われます:
    1. ミューテックスの解放と待機状態への移行
    2. 待機の解除
    3. ロックの再取得
  4. 全順序の保持
    実装は、notify_onenotify_allのすべての実行およびwaitwait_forwait_untilの各部分が、「前に起こる」順序と一致する単一の未定義の全順序で実行されるように振る舞います。
  5. コンストラクションとデストラクション
    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);
  1. 前提条件
    lkは呼び出しスレッドによってロックされており、以下のいずれかを満たしていること:
    • 他のスレッドがcondを待っていない
    • lk.mutex()が、同時に待機しているスレッドすべてに対して同じ値を返す
  2. 効果
    lkに関連付けられたロックの所有権を内部ストレージに移し、現在のスレッドが終了したときにcondを通知するようにスケジュールします。この通知は以下と同等です:
    lk.unlock();
    cond.notify_all();
    
  3. 同期化
    暗黙のlk.unlock()呼び出しは、現在のスレッドに関連するすべてのスレッドストレージ期間のオブジェクトが破壊された後に順序付けられます。
  4. 注記
    • 供給されたロックはスレッドが終了するまで保持されるため、ロックの順序に起因するデッドロックを引き起こす可能性があります。
    • ユーザーは、スプリアスウェイクアップを経験した場合に待機しているスレッドが誤ってスレッドが終了したと仮定しないようにする責任があります。

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();
    };
}
  1. クラスの概要
    condition_variableは標準レイアウトクラスです。
  2. コンストラクタ
    例外が必要な場合、system_errorをスローします。
  3. エラー条件
    • resource_unavailable_try_again — 初期化を妨げる非メモリリソース制限がある場合。
  4. デストラクタの前提条件
    このcondition variable上でブロックされているスレッドがないこと。
  5. notify_one
    このcondition variableを待機しているスレッドがある場合、そのうちの1つを解除します。
  6. notify_all
    このcondition variableを待機しているすべてのスレッドを解除します。
  7. wait
    • 前提条件: lock.owns_lock()がtrueであり、呼び出しスレッドによってlock.mutex()がロックされている。
    • 効果: lock.unlock()を原子的に呼び出し、*thisでブロックします。ブロックが解除されると、lock.lock()を呼び出します。
    • 後条件: lock.owns_lock()がtrueであり、lock.mutex()が呼び出しスレッドによってロックされている。
    • 例外: 何もスローしない。
  8. wait(プレディケート付き)
    • 前提条件: lock.owns_lock()がtrueであり、呼び出しスレッドによってlock.mutex()がロックされている。
    • 効果: プレディケートが満たされるまで待機します。
    • 後条件: lock.owns_lock()がtrueであり、lock.mutex()が呼び出しスレッドによってロックされている。
    • 例外: predによってスローされた任意の例外。
  9. wait_until
    • 前提条件: lock.owns_lock()がtrueであり、呼び出しスレッドによってlock.mutex()がロックされている。
    • 効果: abs_timeに達するまで待機します。
    • 後条件: lock.owns_lock()がtrueであり、lock.mutex()が呼び出しスレッドによってロックされている。
    • 戻り値: cv_status::timeout(タイムアウトした場合)、それ以外はcv_status::no_timeout
    • 例外: タイムアウト関連の例外。
  10. wait_for
    • 前提条件: lock.owns_lock()がtrueであり、呼び出しスレッドによってlock.mutex()がロックされている。
    • 効果: 指定された相対時間rel_timeが経過するまで待機します。
    • 後条件: lock.owns_lock()がtrueであり、lock.mutex()が呼び出しスレッドによってロックされている。
    • 戻り値: cv_status::timeout(タイムアウトした場合)、それ以外はcv_status::no_timeout
    • 例外: タイムアウト関連の例外。
  11. wait_until(プレディケート付き)
    • 前提条件: lock.owns_lock()がtrueであり、呼び出しスレッドによってlock.mutex()がロックされている。
    • 効果: プレディケートが満たされるか、abs_timeに達するまで待機します。
    • 後条件: lock.owns_lock()がtrueであり、lock.mutex()が呼び出しスレッドによってロックされている。
    • 戻り値: predがtrueを返した場合はtrue、それ以外はfalse。
    • 例外: predによってスローされた任意の例外。
  12. wait_for(プレディケート付き)
    • 前提条件: lock.owns_lock()がtrueであり、呼び出しスレッドによってlock.mutex()がロックされている。
    • 効果: プレディケートが満たされるか、指定された相対時間rel_timeが経過するまで待機します。
    • 後条件: lock.owns_lock()がtrueであり、lock.mutex()が呼び出しスレッドによってロックされている。
    • 戻り値: predがtrueを返した場合はtrue、それ以外はfalse。
    • 例外: predによってスローされた任意の例外。
  13. 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();
    };
}
  1. クラスの概要
    condition_variable_anyは標準レイアウトクラスです。
  2. コンストラクタ
    例外が必要な場合、system_errorをスローします。
  3. エラー条件
    • resource_unavailable_try_again — 初期化を妨げる非メモリリソース制限がある場合。
  4. デストラクタの前提条件
    このcondition variable上でブロックされているスレッドがないこと。
  5. notify_one
    このcondition variableを待機しているスレッドがある場合、そのうちの1つを解除します。
  6. notify_all
    このcondition variableを待機しているすべてのスレッドを解除します。
  7. wait
    • 前提条件: lockは呼び出しスレッドによってロックされている。
    • 効果: lock.unlock()を原子的に呼び出し、*thisでブロックします。ブロックが解除されると、lock.lock()を呼び出します。
    • 後条件: lockは呼び出しスレッドによってロックされている。
    • 例外: 何もスローしない。
  8. wait(プレディケート付き)
    • 前提条件: lockは呼び出しスレッドによってロックされている。
    • 効果: プレディケートが満たされるまで待機します。
    • 後条件: lockは呼び出しスレッドによってロックされている。
    • 例外: predによってスローされた任意の例外。
  9. wait_until
    • 前提条件: lockは呼び出しスレッドによってロックされている。
    • 効果: abs_timeに達するまで待機します。
    • 後条件: lockは呼び出しスレッドによってロックされている。
    • 戻り値: cv_status::timeout(タイムアウトした場合)、それ以外はcv_status::no_timeout
    • 例外: タイムアウト関連の例外。
  10. wait_for
    • 前提条件: lockは呼び出しスレッドによってロックされている。
    • 効果: 指定された相対時間rel_timeが経過するまで待機します。
    • 後条件: lockは呼び出しスレッドによってロックされている。
    • 戻り値: cv_status::timeout(タイムアウトした場合)、それ以外はcv_status::no_timeout
    例外:タイムアウト関連の例外。
  11. wait_until(プレディケート付き)
    • 前提条件: lockは呼び出しスレッドによってロックされている。
    • 効果: プレディケートが満たされるか、abs_timeに達するまで待機します。
    • 後条件: lockは呼び出しスレッドによってロックされている。
    • 戻り値: predがtrueを返した場合はtrue、それ以外はfalse。
    • 例外: predによってスローされた任意の例外。
  12. wait_for(プレディケート付き)
    • 前提条件: lockは呼び出しスレッドによってロックされている。
    • 効果: プレディケートが満たされるか、指定された相対時間rel_timeが経過するまで待機します。
    • 後条件: lockは呼び出しスレッドによってロックされている。
    • 戻り値: predがtrueを返した場合はtrue、それ以外はfalse。
    • 例外: predによってスローされた任意の例外。
  13. native_handle
    • 戻り値: 内部の実装定義のネイティブハンドルを返します。