C++プログラミング言語のX86CPUに、効率的でスレッドセーフな参照カウントシステムをどのように実装しますか?
私は常に、重要な操作がアトミックではなく、使用可能なX86インターロック操作が参照カウントシステムを実装するには不十分であるという問題に遭遇します。
次の記事ではこのトピックについて説明していますが、特別なCPU命令が必要です。
C++プログラミング言語のX86CPUに、効率的でスレッドセーフな参照カウントシステムをどのように実装しますか?
私は常に、重要な操作がアトミックではなく、使用可能なX86インターロック操作が参照カウントシステムを実装するには不十分であるという問題に遭遇します。
次の記事ではこのトピックについて説明していますが、特別なCPU命令が必要です。
最近では、Boost/TR1 shared_ptr<> スマート ポインターを使用して、参照カウント参照を維持できます。
よく働く; 大騒ぎする必要はありません。shared_ptr<> クラスは、refcount で必要なすべてのロックを処理します。
In VC++, you can use _InterlockedCompareExchange.
do
read the count
perform mathematical operation
interlockedcompareexchange( destination, updated count, old count)
until the interlockedcompareexchange returns the success code.
On other platforms/compilers, use the appropriate intrinsic for the LOCK CMPXCHG instruction that MS's _InterlockedCompareExchange exposes.
厳密に言えば、純粋な C++ でスレッドセーフ コードを記述できるようになるには、C++0x まで待つ必要があります。
今のところ、Posix を使用するか、独自のプラットフォームに依存しないラッパーを作成して、比較とスワップおよび/またはインターロックされたインクリメント/デクリメントを処理できます。
Win32 の InterlockedIncrementAcquire と InterlockedDecrementRelease (安全を確保し、並べ替えの可能性があるプラットフォームを考慮したい場合は、メモリ バリアを同時に発行する必要があります) または InterlockedIncrement と InterlockedDecrement (x86 のままでいることが確実な場合) はアトミックであり、仕事をする。
とはいえ、Boost/TR1 shared_ptr<> はこれらすべてを処理するため、独自に実装する必要がない限り、おそらくそれに固執するために最善を尽くすでしょう。
ロックは非常に高価であり、オブジェクトが現在 1 つのスレッドによって所有されている場合でも、スマート ポインター間でオブジェクトを渡すたびに発生することに注意してください (スマート ポインター ライブラリはそれを認識していません)。
これを考えると、ここに適用できる経験則があるかもしれません (修正できてうれしいです!)
以下の事項に該当する場合:
...その後、実際のガベージコレクションの方が良い選択かもしれません。GC のパフォーマンスは評判が悪いですが、それはすべて相対的なものです。スマート ポインターのロックと比べて非常に有利だと思います。これは、CLR チームが参照カウントを使用するものではなく真の GC を選択した理由の重要な部分でした。この記事を参照してください。特に、カウントが行われている場合の参照割り当ての意味のこの明確な比較を参照してください。
参照カウントなし:
a = b;
参照カウント:
if (a != null)
if (InterlockedDecrement(ref a.m_ref) == 0)
a.FinalRelease();
if (b != null)
InterlockedIncrement(ref b.m_ref);
a = b;
その ddj 記事に投稿された特定のコードは、スマート ポインターを使用する際のバグを考慮して複雑さを増しています。
具体的には、スマート ポインターが別のスマート ポインターへの代入で変更されないことを保証できない場合は、それが間違っているか、そもそも非常に信頼できないことを行っています。スマート ポインターが別のスマート ポインターに割り当てられている間に変化する可能性がある場合、それは割り当てを行うコードがスマート ポインターを所有していないことを意味します。
命令自体がアトミックでない場合は、適切な変数を更新するコードのセクションをクリティカル セクションにする必要があります。
つまり、何らかのロック方式を使用して、他のスレッドがコードのそのセクションに入るのを防ぐ必要があります。もちろん、ロックはアトミックである必要がありますが、アトミック ロック メカニズムは pthread_mutex クラス内にあります。
効率性の問題: pthread ライブラリは可能な限り効率的であり、OS に対してミューテックス ロックがアトミックであることを保証します。
高いですか:おそらく。しかし、保証が必要なすべてのものにはコストがかかります。