another questionの回答を書くと、興味深いことがいくつか出てきましたが、今は理解できません。Interlocked.Increment(ref long value)
は32ビットシステムで動作します。私に説明させてください。 32ビット環境用にコンパイルするとき32ビット環境で64ビット変数のアトミックインクリメント
ネイティブInterlockedIncrement64
が現在利用可能ではない、OK、必要に応じて.NETにあなたがメモリを揃えることができないので、それが理にかなって、それがから呼び出すことが、彼らはそれを落とした後、を管理していました。
我々は64ビットの変数を参照してInterlocked.Increment()
を呼び出すことができ、(我々はFieldOffset
とStructLayout
を使用することができる場合も、構造中に例えば)我々はまだ、そのアライメントに関する制約を持たないが、ドキュメントはdoesnのどのような制限(AFAIK)も言及していない。それは魔法です、それは動作します!
ハンスアンパッサンInterlocked.Increment()
は、JITコンパイラによって認識特別方法であり、それは、同じ制限をInterlockedIncrement64のを共有InterlockedExchangeAdd64マクロあるFastInterlockExchangeAddLongを呼び出すれるCOMInterlocked::ExchangeAdd64()にコールを発することに留意。
今、私は困惑しています。
1秒間の管理環境を忘れてネイティブに戻ってください。なぜInterlockedIncrement64
は機能しませんが、InterlockedExchangeAdd64
は機能しますか?組み込み関数が利用できないとInterlockedExchangeAdd64
作品は、それはInterlockedExchangeAdd64
への呼び出しとして実施することができる場合InterlockedIncrement64
は...、マクロです
さんが戻っ管理へ行こう:原子64ビットの増分が32ビットシステム上で実装されていますか?私は文章があると思います"この関数は他のインターロック関数への呼び出しに関してはアトミックです"が重要ですが、それでもコードはありませんでした。組み込み関数が利用できないときのがWinBase.hからInterlockedExchangedAdd64
実装を選択してみましょう:
FORCEINLINE
LONGLONG
InterlockedExchangeAdd64(
_Inout_ LONGLONG volatile *Addend,
_In_ LONGLONG Value
)
{
LONGLONG Old;
do {
Old = *Addend;
} while (InterlockedCompareExchange64(Addend,
Old + Value,
Old) != Old);
return Old;
}
それはどのように読み取り/書き込みのため、原子することができますか?
「InterlockedIncrement64」は動作しませんが、「InterlockedExchangeAdd64」は「?独自の答えは、マネージコードがネイティブのWin32 APIを直接呼び出すことはできず、すべてが動作することを期待しているという点では正しいです。どちらもうまくいきません。管理ヘルパーを使用する必要があります。現在、マネージヘルパーの実装はネイティブコードなので、ネイティブ関数を呼び出します。コンパイル時にマクロと組み込み関数が解決されるため、CLRのビット数が重要です。 –
はい、ただし32ビットJITは、InterlockedIncrement64と同じ制限(ネイティブ)を持つInterlockedExchangeAdd64を呼び出します。私が理解できなかったことは、(マネージコードのために呼び出されたときのメモリの整列のために)それがどのように行われるかです。 32ビットの実装ではInterlockedCompareExchange64を使用しています... ... hmmm ....アトミックではないかもしれません(結果を返すために...) –
* "読み書きのためにはどうしたらアトミックになりますか?" * InterlockedExchangeAdd64ヒントのドキュメント"この関数は、メモリ操作が順番に完了するようにするために、完全なメモリバリア(またはフェンス)を生成します。" *上記の実装は、 'InterlockedCompareExchange64'を呼び出していることに注意してください。 32ビットのビルドでは、これは 'LOCK'プレフィックスを持つ' CMPXCHG8B'命令を発行します。これにより、命令がアトミックに実行されます。ロックされた書き込みがない状態でロックされた読み込みを得ることはないので、書き込み先はアトミックです。 –