std::counting_semaphore, std::binary_semaphore
| ヘッダー <semaphore>で定義 |
||
| template< std::ptrdiff_t LeastMaxValue = /* 実装定義 */ > class counting_semaphore; |
(1) | (C++20以降) |
| using binary_semaphore = std::counting_semaphore<1>; |
(2) | (C++20以降) |
counting_semaphore は、共有リソースへのアクセスを制御できる軽量な同期プリミティブです。std::mutexとは異なり、counting_semaphore は、少なくとも LeastMaxValue の同時アクセス者に対して、同じリソースへの複数の同時アクセスを許可します。LeastMaxValue が負の場合、プログラムは不正です。binary_semaphore は、LeastMaxValue が 1 である std::counting_semaphore の特殊化のエイリアスです。実装によっては、binary_semaphore を std::counting_semaphore のデフォルト実装よりも効率的に実装できます。counting_semaphore は、コンストラクタによって初期化される内部カウンタを保持します。このカウンタは、acquire() および関連メソッドの呼び出しによってデクリメントされ、release() の呼び出しによってインクリメントされます。カウンタがゼロの場合、acquire() はカウンタがインクリメントされるまでブロックしますが、try_acquire() はブロックしません。try_acquire_for() および try_acquire_until() は、カウンタがインクリメントされるかタイムアウトに達するまでブロックします。
std::condition_variable::wait() と同様に、counting_semaphore の try_acquire() は偶発的に失敗する可能性があります。
std::counting_semaphore の特殊化は、DefaultConstructible、CopyConstructible、MoveConstructible、CopyAssignable、または MoveAssignable ではありません。
目次 |
[編集] データメンバ
| メンバ名 | 定義 |
counter (private) |
型 std::ptrdiff_t の内部カウンタ。 (説明用のメンバオブジェクト*) |
[編集] メンバ関数
counting_semaphore を構築する(public メンバ関数) | |
counting_semaphore を破棄する(public メンバ関数) | |
| operator= [削除] |
counting_semaphore は代入不可(public メンバ関数) |
操作 | |
| 内部カウンタをインクリメントし、アクライアをブロック解除する (public メンバ関数) | |
| 内部カウンタをデクリメントするか、デクリメントできるまでブロックする (public メンバ関数) | |
| ブロックせずに内部カウンタをデクリメントしようとする (public メンバ関数) | |
| 内部カウンタをデクリメントしようと試み、duration 時間までブロックする (public メンバ関数) | |
| 内部カウンタをデクリメントしようと試み、特定の時点までブロックする (public メンバ関数) | |
定数 | |
| [static] |
内部カウンタの最大可能値を返す (public static メンバ関数) |
[編集] 注釈
その名前が示すように、LeastMaxValue は最小の最大値であり、実際の最大値ではありません。したがって、max() は LeastMaxValue より大きい数値を返すことがあります。
std::mutex とは異なり、counting_semaphore は実行スレッドに結びついていません。たとえば、セマフォのアクワイアは、セマフォのリリースとは異なるスレッドで発生する可能性があります。counting_semaphore のすべての操作は、同時に、特定の実行スレッドとは無関係に実行できます。ただし、デストラクタは同時に実行することはできませんが、異なるスレッドで実行できます。
セマフォは、相互排他ではなく、シグナリング/通知のセマンティクスにもよく使用されます。これは、セマフォを 0 で初期化することで、acquire() しようとするレシーバをブロックし、通知者が release(n) を呼び出すことで「シグナル」を送るまで待機させるものです。この点において、セマフォは std::condition_variable の代替と見なすことができ、多くの場合、より優れたパフォーマンスを発揮します。
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_semaphore |
201907L |
(C++20) | std::counting_semaphore, std::binary_semaphore |
[編集] 例
#include <chrono> #include <iostream> #include <semaphore> #include <thread> // global binary semaphore instances // object counts are set to zero // objects are in non-signaled state std::binary_semaphore smphSignalMainToThread{0}, smphSignalThreadToMain{0}; void ThreadProc() { // wait for a signal from the main proc // by attempting to decrement the semaphore smphSignalMainToThread.acquire(); // this call blocks until the semaphore's count // is increased from the main proc std::cout << "[thread] Got the signal\n"; // response message // wait for 3 seconds to imitate some work // being done by the thread using namespace std::literals; std::this_thread::sleep_for(3s); std::cout << "[thread] Send the signal\n"; // message // signal the main proc back smphSignalThreadToMain.release(); } int main() { // create some worker thread std::thread thrWorker(ThreadProc); std::cout << "[main] Send the signal\n"; // message // signal the worker thread to start working // by increasing the semaphore's count smphSignalMainToThread.release(); // wait until the worker thread is done doing the work // by attempting to decrement the semaphore's count smphSignalThreadToMain.acquire(); std::cout << "[main] Got the signal\n"; // response message thrWorker.join(); }
出力
[main] Send the signal [thread] Got the signal [thread] Send the signal [main] Got the signal