std::atomic<std::shared_ptr>
| ヘッダ <memory> で定義 |
||
| template< class T > struct std::atomic<std::shared_ptr<T>>; |
(C++20以降) | |
std::atomicのstd::shared_ptr<T>の部分特殊化により、ユーザーはshared_ptrオブジェクトをアトミックに操作できます。
複数の実行スレッドが同じstd::shared_ptrオブジェクトに同期なしでアクセスし、それらのアクセスにshared_ptrの非constメンバ関数が使用される場合、そのようなすべてのアクセスがstd::atomic<std::shared_ptr>のインスタンスを介して(または、C++20以降非推奨ですが、std::shared_ptrへのアトミックアクセス用のスタンドアローン関数を介して)実行されない限り、データ競合が発生します。
関連する`use_count`のインクリメントは、アトミック操作の一部であることが保証されます。関連する`use_count`のデクリメントは、アトミック操作の後に順序付けられますが、アトミック操作の一部である必要はありません。ただし、失敗したCASで`expected`を上書きする際の`use_count`の変更は除きます。関連する削除とデアロケーションは、アトミック更新ステップの後に順序付けられ、アトミック操作の一部ではありません。
shared_ptrのコントロールブロックはスレッドセーフであることに注意してください。異なる非アトミックなstd::shared_ptrオブジェクトは、operator=やresetなどの変更可能な操作を使用して、複数のスレッドによって同時にアクセスできます。これらのインスタンスがコピーであり、内部的に同じコントロールブロックを共有している場合でも同様です。
型Tは不完全型であってもよい。
[編集] メンバ型
| メンバ型 | 定義 |
value_type
|
std::shared_ptr<T> |
[編集] メンバ関数
非特殊化されたstd::atomicのすべての関数は、この特殊化でも提供され、追加のメンバ関数はありません。
| constexpr atomic() noexcept = default; |
(1) | |
| constexpr atomic( std::nullptr_t ) noexcept : atomic() {} |
(2) | |
| atomic( std::shared_ptr<T> desired ) noexcept; |
(3) | |
| atomic( const atomic& ) = delete; |
(4) | |
| void operator=( const atomic& ) = delete; |
(1) | |
| void operator=( std::shared_ptr<T> desired ) noexcept; |
(2) | |
| void operator=( std::nullptr_t ) noexcept; |
(3) | |
| bool is_lock_free() const noexcept; |
||
この型のすべてのオブジェクトに対するアトミック操作がロックフリーであればtrue、そうでなければfalseを返します。
| void store( std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |
||
基底のstd::shared_ptr<T>であるpに対してp.swap(desired)を実行するように、*thisの値をアトミックにdesiredの値に置き換えます。メモリはorderに従って順序付けられます。orderがstd::memory_order_consume、std::memory_order_acquire、またはstd::memory_order_acq_relの場合、動作は未定義です。
| std::shared_ptr<T> load( std::memory_order order = std::memory_order_seq_cst ) const noexcept; |
||
基底のshared pointerのコピーをアトミックに返します。メモリはorderに従って順序付けられます。orderがstd::memory_order_releaseまたはstd::memory_order_acq_relの場合、動作は未定義です。
| std::shared_ptr<T> exchange( std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |
||
基底のstd::shared_ptr<T>であるpに対してp.swap(desired)を実行するように、アトミックに基底のstd::shared_ptr<T>をdesiredに置き換え、交換直前のpの値のコピーを返します。メモリはorderに従って順序付けられます。これはアトミックな読み取り-変更-書き込み操作です。
| bool compare_exchange_strong( std::shared_ptr<T>& expected, std::shared_ptr<T> desired, std::memory_order success, std::memory_order failure ) noexcept; |
(1) | |
| bool compare_exchange_weak( std::shared_ptr<T>& expected, std::shared_ptr<T> desired, std::memory_order success, std::memory_order failure ) noexcept; |
(2) | |
| bool compare_exchange_strong( std::shared_ptr<T>& expected, std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |
(3) | |
| bool compare_exchange_weak( std::shared_ptr<T>& expected, std::shared_ptr<T> desired, std::memory_order order = std::memory_order_seq_cst ) noexcept; |
(4) | |
use_countへの更新は、このアトミック操作の一部ですが、書き込み自体(およびその後の解放/破棄)はそうである必要はありません。fail_orderがorderと同じで、ただしstd::memory_order_acq_relがstd::memory_order_acquireに、std::memory_order_releaseがstd::memory_order_relaxedに置き換えられる場合、return compare_exchange_strong(expected, desired, order, fail_order); と同等です。fail_orderがorderと同じで、ただしstd::memory_order_acq_relがstd::memory_order_acquireに、std::memory_order_releaseがstd::memory_order_relaxedに置き換えられる場合、return compare_exchange_weak(expected, desired, order, fail_order); と同等です。| void wait( std::shared_ptr<T> old, std::memory_order order = std::memory_order_seq_cst ) const noexcept; |
||
アトミックな待機操作を実行します。
load(order)とoldを比較し、これらが等しい場合、notify_one()またはnotify_all()によって*thisが通知されるまでブロックします。これはload(order)が変更されるまで繰り返されます。この関数は、基底の実装が偽りにブロックを解除した場合でも、値が変更された場合にのみ返ることが保証されます。
メモリはorderに従って順序付けられます。orderがstd::memory_order_releaseまたはstd::memory_order_acq_relの場合、動作は未定義です。
注: 2つの`shared_ptr`は、同じポインタを格納し、所有権を共有しているか、両方とも空である場合に等価です。
| void notify_one() noexcept; |
||
アトミックな通知操作を実行します。
*thisでアトミック待機操作(すなわちwait())でブロックされているスレッドがある場合、少なくとも1つのスレッドのブロックを解除します。それ以外の場合は何もしません。
| void notify_all() noexcept; |
||
アトミックな通知操作を実行します。
*thisでアトミック待機操作(すなわちwait())によってブロックされているスレッドがある場合、すべてのスレッドのブロックを解除します。それ以外の場合は何もしません。
[編集] メンバ定数
この特殊化によっても、標準のstd::atomicメンバ定数is_always_lock_freeが提供されます。
| static constexpr bool is_always_lock_free = /*実装定義*/; |
||
[編集] ノート
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_lib_atomic_shared_ptr |
201711L |
(C++20) | std::atomic<std::shared_ptr>
|
[編集] 例
| このセクションは未完成です 理由: 例がありません |
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 3661 | C++20 | atomic<shared_ptr<T>>はnullptrから定数初期化可能ではなかった |
定数初期化可能になった |
| LWG 3893 | C++20 | LWG3661によりatomic<shared_ptr<T>>がnullptr_tから代入できなくなった |
代入可能性が回復 |
[編集] 関連項目
| (C++11) |
アトミッククラステンプレートと、bool、整数、浮動小数点数、(C++20以降)、ポインタ型のための特殊化 (クラステンプレート) |