11

別の質問に対する回答を書いていると、興味深いことがいくつか出てきましたが、今ではInterlocked.Increment(ref long value)32 ビット システムでどのように動作するのか理解できません。説明させてください。

32ビット環境用にコンパイルするときにネイティブInterlockedIncrement64を使用できなくなりました.OK..NETでは必要に応じてメモリを配置できず、マネージから呼び出されて削除される可能性があるため、これは理にかなっています.

.NETではInterlocked.Increment()、64ビット変数への参照を使用して呼び出すことができますが、その配置に関する制約はまだありません(たとえば、構造内で and を使用する場合もありますFieldOffsetStructLayoutが、ドキュメントには制限については言及されていません(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;
}

読み取り/書き込みをアトミックにするにはどうすればよいですか?

4

1 に答える 1

9

InterlockedExchangeAdd64() は、WinNt.h SDK ヘッダー ファイルに移動します。ターゲット アーキテクチャに応じて、多くのバージョンが表示されます。

これは一般に次のようにまとめられます。

#define InterlockedExchangeAdd64 _InterlockedExchangeAdd64

これは、vc/include/intrin.h で宣言され、コンパイラのバックエンドによって実装されるコンパイラの組み込みにバックを渡します。

つまり、CLR のビルドが異なれば、CLR の実装も異なります。何年にもわたって、x86、x64、Itanium、ARM、ARM8、PowerPC など、思い浮かんだことがたくさんありました。Apple が WindowsCE を無関係にする前に WindowsCE を起動していたものを見逃していることは確かです。x86 の場合、これは最終的に LOCK CMPXCHNG8B によって処理されます。これは、位置合わせされていない 64 ビット変数を処理できる専用のプロセッサ命令です。他の 32 ビット プロセッサでどのように表示されるかを確認するためのハードウェアがありません。

マネージ コードのターゲット アーキテクチャはコンパイル時に決定されないことに注意してください。実行時に MSIL をターゲットに適応させるのはジッターです。/clr:pure の代わりに /clr を使用してコンパイルし、x86 と x64 のみが機能する場合、通常はターゲットを選択する必要があるため、これは C++/CLI プロジェクトにはあまり関係ありません。しかし、とにかく配管が整っているので、マクロはあまり役に立ちません。

于 2016-06-01T07:42:17.143 に答える