別の質問に対する回答を書いていると、興味深いことがいくつか出てきましたが、今ではInterlocked.Increment(ref long value)
32 ビット システムでどのように動作するのか理解できません。説明させてください。
32ビット環境用にコンパイルするときにネイティブInterlockedIncrement64
を使用できなくなりました.OK..NETでは必要に応じてメモリを配置できず、マネージから呼び出されて削除される可能性があるため、これは理にかなっています.
.NETではInterlocked.Increment()
、64ビット変数への参照を使用して呼び出すことができますが、その配置に関する制約はまだありません(たとえば、構造内で and を使用する場合もありますFieldOffset
)StructLayout
が、ドキュメントには制限については言及されていません(AFAIK )。それは魔法です、それはうまくいきます!
Hans Passant は、これはJIT コンパイラによって認識される特別なメソッドであり、COMInterlocked::ExchangeAdd64() への呼び出しを Interlocked.Increment()
発行し、次にInterlockedExchangeAdd64の同じ制限を共有するInterlockedExchangeAdd64のマクロであるFastInterlockExchangeAddLongを呼び出すことに注意しました。
今、私は困惑しています。
管理された環境を 1 秒間忘れて、ネイティブに戻ります。なぜ機能しInterlockedIncrement64
ないのに機能するのInterlockedExchangeAdd64
ですか?InterlockedIncrement64
はマクロです。組み込み関数が利用できず、動作する場合は、 ...InterlockedExchangeAdd64
への呼び出しとして実装できます。InterlockedExchangeAdd64
マネージドに戻りましょう: アトミック 64 ビット インクリメントは 32 ビット システムでどのように実装されるのでしょうか? 「この関数は、他のインターロックされた関数の呼び出しに関して原子的です」という文は重要だと思いますが、それを行うためのコードはまだ見当たりませんでした(より深い実装を指摘してくれたハンスに感謝します)。InterlockedExchangedAdd64
組み込み関数が利用できない場合は、WinBase.h から実装を選択しましょう。
FORCEINLINE
LONGLONG
InterlockedExchangeAdd64(
_Inout_ LONGLONG volatile *Addend,
_In_ LONGLONG Value
)
{
LONGLONG Old;
do {
Old = *Addend;
} while (InterlockedCompareExchange64(Addend,
Old + Value,
Old) != Old);
return Old;
}
読み取り/書き込みをアトミックにするにはどうすればよいですか?