4

Boost 1.5.1 ソースの下にsmart_ptr\detail\atomic_count_win32.hppは、きちんとした小さなアトミック参照カウンターがありboost::detail::atomic_countます。

48行目で、彼らは私が興味を持っているキャストを行います:

class atomic_count
{
public:

// ...

operator long() const
{
    return static_cast<long const volatile &>( value_ );
}

private:
long value_;

カウンタ値が a-reference-to-a-volatile-constant-long ( long const volatile&) にキャストされるのはなぜですか?

4

2 に答える 2

5

MSVC は、変数に非推奨の拡張機能volatile提供し、セマンティクスの取得と解放を提供します (マルチスレッド プログラミングに関して、メモリ順序の保証)。

このキャストは、変数でこの拡張機能を「有効」にし、読み取りと取得のセマンティクスを与えます (発生する可能性のある解放と書き込みに一致させるため)。繰り返しますが、これは非標準です。C++11 コードでは、 を使用する必要がありますstd::atomic<>

マルチスレッド (共有) 使用boost::shared_ptrでの正確性が保証されるため、これが必要です。shared_ptr<T>これは、ロックフリーカウンターの実装です。

(また、これは話の半分にすぎません: この拡張機能は必要な順序付けと可視性の保証を提供するかもしれませんが、アトミック性を保証するものではありません。Win32 では、これはそれが実行されるプラットフォームによって暗黙的に保証されます:プラットフォームごとにアトミックです。)

開始する前に芽を摘むには: この拡張機能volatileがないと、マルチスレッド プログラミングには役に立ちません。試してはいけません。この拡張機能は推奨されていないため、可能であれば使用しないでください。

于 2012-12-03T20:18:14.913 に答える
1

x86 プラットフォームでは、ネイティブ幅の位置合わせされた値の場合、これで十分であることがわかっています。

彼らが回避しようとしている問題は次のとおりです。

  1. 変数には 16 進値があります0000FFFF

  2. スレッド A は値の読み取りを開始し、0000xxxxパーツを取得します。

  3. スレッド B は値を から0000FFFFにインクリメントします00010000

  4. スレッド A は値の読み取りを終了し、xxxx0000まだ読み取っていない部分を取得します。

  5. スレッド A は00000000!の値を読み取りました。

これをワードテアリングと呼びます。ただし、これは、x86 のネイティブ幅の整列された型では発生しないことが知られています。そのため、単なるキャスト スルーvolatile(問題のあるコンパイラの最適化を回避することが知られている) だけで十分です。

これは一般的な真実ではないことに注意してください。これはたまたまプラットフォームのプロパティです。これは移植可能なコードではありません。

于 2012-12-03T20:17:20.447 に答える