英語版
このページの英語版を見る

core.atomic

アトミック・モジュールはロックフリーの アトミック・モジュールは、ロックフリーの並行プログラミングの基本的なサポートを提供する。
注釈:共有データに対する安全でない個々の読み取りまたは書き込み操作を検出するには、-preview=nosharedaccess コンパイラー・フラグを使用する。 を使用する。
Authors:
Sean Kelly, Alex Rønne Petersen, Manu Evans

ソース core/atomic.d

Examples:
int y = 2;
shared int x = y; // OK

//x++; // 読み込み変更書き込みエラー
x.atomicOp!"+="(1); // OK
//y = x; // プレビュー・フラグによる読み取りエラー
y = x.atomicLoad(); // OK
assert(y == 3);
//x = 5; // プレビュー・フラグによる書き込みエラー
x.atomicStore(5); // OK
assert(x.atomicLoad() == 5);
enum MemoryOrder: int;
アトミック操作のメモリ順序セマンティクスを指定する。
raw
順序付けしない。 LLVM AtomicOrdering.Monotonicに対応する。 および C++11/C11memory_order_relaxed に対応する。
acq
ホイストロード+ホイストストアバリア。 LLVM AtomicOrdering.Acquireに対応する。 および C++11/C11memory_order_acquire に対応する。
rel
シンクロード + シンクストア障壁。 LLVM AtomicOrdering.Releaseに対応する。 および C++11/C11memory_order_release に対応する。
acq_rel
Acquire + Release バリア。 LLVM AtomicOrdering.AcquireReleaseに対応する。 および C++11/C11memory_order_acq_rel に対応する。
seq
完全シーケンス(acquire + release)。以下に対応する LLVM AtomicOrdering.SequentiallyConsistent および C++11/C11 に対応する。 および C++11/C11memory_order_seq_cst に対応する。
pure nothrow @nogc @trusted T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope const T val)
if (!is(T == shared(U), U) && !is(T == shared(inout(U)), U) && !is(T == shared(const(U)), U));

pure nothrow @nogc @trusted T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope const shared T val)
if (!hasUnsharedIndirections!T);

pure nothrow @nogc @trusted TailShared!T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto const shared ref T val)
if (hasUnsharedIndirections!T);
val' をメモリからロードして返す。 ms' で指定されたメモリバリアが適用される。 ms' で指定されたメモリバリアが適用される。 で指定されたメモリバリアが適用される。 有効なメモリ順序は、MemoryOrder.raw、MemoryOrder.acq、 および MemoryOrder.seq である。
Parameters:
T val ターゲット変数。
Returns:
val'の値。
pure nothrow @nogc @trusted void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val, V newval)
if (!is(T == shared) && !is(V == shared));

pure nothrow @nogc @trusted void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(shared ref T val, V newval)
if (!is(T == class));

pure nothrow @nogc @trusted void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(shared ref T val, auto shared ref V newval)
if (is(T == class));
newval' を 'val' に書き込む。 ms' で指定されたメモリバリアが適用される。 で指定されたメモリバリアが適用される。 有効なメモリ順序は、MemoryOrder.raw、MemoryOrder.rel、および である。
Parameters:
T val ターゲット変数。
V newval 格納する値。
pure nothrow @nogc @trusted T atomicFetchAdd(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope T val, size_t mod)
if ((__traits(isIntegral, T) || is(T == U*, U)) && !is(T == shared));

pure nothrow @nogc @trusted T atomicFetchAdd(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope shared T val, size_t mod)
if (__traits(isIntegral, T) || is(T == U*, U));
アトミックに modで参照される値にアトミックに加算する。 valで参照される値にアトミックに加算し、その値を返す。 valを返す。 この操作はロックフリーかつアトミックである。
Parameters:
T val 変更する値への参照。
size_t mod 追加する値。
Returns:
によって以前に保持されていた値。 val.
pure nothrow @nogc @trusted T atomicFetchSub(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope T val, size_t mod)
if ((__traits(isIntegral, T) || is(T == U*, U)) && !is(T == shared));

pure nothrow @nogc @trusted T atomicFetchSub(MemoryOrder ms = MemoryOrder.seq, T)(ref return scope shared T val, size_t mod)
if (__traits(isIntegral, T) || is(T == U*, U));
原子的に modで参照される値からアトミックに引く。 valによって参照される値からアトミックに減算し、その値を返す。 valによって参照される値からアトミックに減算して返す。 この操作はロックフリーかつアトミックである。
Parameters:
T val 変更する値への参照。
size_t mod 減算する値。
Returns:
によって以前に保持されていた値。 val.
pure nothrow @nogc @trusted T atomicExchange(MemoryOrder ms = MemoryOrder.seq, T, V)(T* here, V exchangeWith)
if (!is(T == shared) && !is(V == shared));

pure nothrow @nogc @trusted TailShared!T atomicExchange(MemoryOrder ms = MemoryOrder.seq, T, V)(shared(T)* here, V exchangeWith)
if (!is(T == class) && !is(T == interface));

pure nothrow @nogc @trusted shared(T) atomicExchange(MemoryOrder ms = MemoryOrder.seq, T, V)(shared(T)* here, shared(V) exchangeWith)
if (is(T == class) || is(T == interface));
交換する exchangeWithが参照するメモリと交換する。 here. この操作はロックフリーかつアトミックである。
Parameters:
T* here 交換先変数のアドレス。
V exchangeWith 交換する値。
Returns:
によって以前に保持されていた値。 here.
template cas(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq)
compare-and-setまたはcompare-and-swap(またはexchange)を実行する。
このテンプレートには2種類のオーバーロードがある: 最初のカテゴリーは単純な compare-and-set を行う。 比較値(ifThis)はr値として扱われる。
2つ目のカテゴリーはcompare-and-swap(別名compare-and-exchange)である、 を行い、ifThis がポインタ型であることを期待する。 here の前の値が書き込まれる。
この操作はロックフリーでアトミックである。
Parameters:
T* here 格納先変数のアドレス。
V2 writeThis 格納する値。
V1 ifThis 比較値
Returns:
ストアが行われた場合はtrue、行われなかった場合はfalse。
pure nothrow @nogc @trusted bool cas(T, V1, V2)(T* here, V1 ifThis, V2 writeThis)
if (!is(T == shared) && is(T : V1));
共有でない値の比較とセット
pure nothrow @nogc @trusted bool cas(T, V1, V2)(shared(T)* here, V1 ifThis, V2 writeThis)
if (!is(T == class) && (is(T : V1) || is(shared(T) : V1)));
共有値型の Compare-and-set
pure nothrow @nogc @trusted bool cas(T, V1, V2)(shared(T)* here, shared(V1) ifThis, shared(V2) writeThis)
if (is(T == class));
shared 参照型(class )に対する比較-アンド-セット。
pure nothrow @nogc @trusted bool cas(T, V)(T* here, T* ifThis, V writeThis)
if (!is(T == shared) && !is(V == shared));
shared 型に対する Compare-and-exchange
pure nothrow @nogc @trusted bool cas(T, V1, V2)(shared(T)* here, V1* ifThis, V2 writeThis)
if (!is(T == class) && (is(T : V1) || is(shared(T) : V1)));
Compare-and-exchange for mixed-sharedness タイプ
pure nothrow @nogc @trusted bool cas(T, V)(shared(T)* here, shared(T)* ifThis, shared(V) writeThis)
if (is(T == class));
の比較と交換class
pure nothrow @nogc @trusted bool casWeak(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2)(T* here, V1 ifThis, V2 writeThis)
if (!is(T == shared) && is(T : V1));

pure nothrow @nogc @trusted bool casWeak(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2)(shared(T)* here, V1 ifThis, V2 writeThis)
if (!is(T == class) && (is(T : V1) || is(shared(T) : V1)));

pure nothrow @nogc @trusted bool casWeak(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2)(shared(T)* here, shared(V1) ifThis, shared(V2) writeThis)
if (is(T == class));
here'によって参照される値が等しい場合、'writeThis'を'here'によって参照されるメモリに格納する。 here'が参照する値が'ifThis'と等しい場合、'writeThis'を'here'が参照するメモリに格納する。 casの'weak'バージョンはスプリアスに失敗するかもしれない。そのため を使うことを推奨する。 casWeakcas がループの中で使われる場合にのみ使うことを推奨する。 この操作は ロックフリーかつアトミックである。
Parameters:
T* here 格納先変数のアドレス。
V2 writeThis 格納する値。
V1 ifThis 比較値
Returns:
格納が行われた場合はtrue、行われなかった場合はfalseを返す。
pure nothrow @nogc @trusted bool casWeak(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V)(T* here, T* ifThis, V writeThis)
if (!is(T == shared(S), S) && !is(V == shared(U), U));

pure nothrow @nogc @trusted bool casWeak(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V1, V2)(shared(T)* here, V1* ifThis, V2 writeThis)
if (!is(T == class) && (is(T : V1) || is(shared(T) : V1)));

pure nothrow @nogc @trusted bool casWeak(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T, V)(shared(T)* here, shared(T)* ifThis, shared(V) writeThis)
if (is(T == class));
もし'here'が参照する値と'ifThis'が参照する値が等しければ、'writeThis'を'here'が参照するメモリに格納する。 here'が参照する値が'ifThis'が参照する値と等しい場合、'writeThis'を'here'が参照するメモリに格納する。 here'で参照される前の値が、'writeThis'に書き込まれる。 ifThisに書き込まれ に返される。 casの'weak'バージョンはスプリアスに失敗するかもしれない。そのため を使うことを推奨する。 casWeakを使うことが推奨される。cas がループの中で使われる場合のみである。 この操作はロックフリーでアトミックである。
Parameters:
T* here 格納先変数のアドレス。
V writeThis 格納する値。
T* ifThis 比較する値のアドレス。 hereを出力として受け取る。
Returns:
ストアが行われた場合はtrue、行われなかった場合はfalseを返す。
pure nothrow @nogc @safe void atomicFence(MemoryOrder order = MemoryOrder.seq)();
完全なロード/ストア・メモリー・フェンスを挿入する(それが必要なプラットフォームで)。これにより これは、この関数を呼び出す前のすべてのロードとストアが、呼び出した後のロードとストアの前に実行されることを保証する。 の前に実行される。
pure nothrow @nogc @safe void pause();
呼び出し元のスレッドが「スピン待ち」ループにあることをプロセッサに知らせる、 より効率的にリソースを割り当てることができる。
pure nothrow @nogc @safe TailShared!T atomicOp(string op, T, V1)(shared ref T val, V1 mod)
if (__traits(compiles, mixin("*cast(T*)&val" ~ op ~ "mod")));
修飾子として'mod'を使用して、valに対してバイナリ演算'op'を実行する。
Parameters:
T val 対象となる変数。
V1 mod 適用する修飾子。
Returns:
処理結果。