3

std::shared_ptr参照カウントを保持するヒープに制御ブロックを割り当てる必要があります。http://ootips.org/yonat/4dev/smart-pointers.htmlから学んだ別のアプローチがあり、これはすべての参照を二重にリンクされたリストに保持します。追加の割り当てやカウンターは必要ありませんが、参照オブジェクト自体は大きくなります。

ある実装が他の実装よりも優れていることを示すベンチマークまたは明確な理由はありますか?

4

1 に答える 1

8

この標準では、理論的にはリンクリストの使用が許可されていますが、コピーはshared_ptrスレッドセーフである必要があるため、リンクリストを使用して実装するのは困難です。shared_ptrリストはミューテックスで保護する必要があります(またはロックフリーリストである必要があります。これははるかに困難です)。これにより、aがコピーされるかスコープ外になるたびに、リストを複数のスレッドで安全に変更できます。

アトミックタイプを使用して参照カウントを実行し、参照カウントの更新にアトミック操作を使用する方がはるかに簡単で、一般的に効率的です。

編集:以下のコメントに答えるには、リンクリストを実装するためにアトミックポインタを使用するだけでは十分ではありません。リストにノードを追加またはリストから削除するには(これは、の増減に対応しuse_countます)、2つのポインターをアトミックに更新して、ノードの追加/削除の前後のノードのリンクを調整する必要があります。 std::atomic<T*>単一のポインターをアトミックに更新できますが、そのような2つのオブジェクトをアトミックに更新する必要がある場合は役に立ちません。これらの2つのポインターは別々のノードに存在するため、隣接していないため、クアッドワードCASでも役に立ちません。

代替案は、リスト全体を保護するミューテックス(明らかに競合に悪い)または更新に関係する各ノードのミューテックスをロックするリストノードごとのミューテックスです。これは、より多くのメモリを使用し、一度に最大3つのノードに影響します。つまり、ロックが必要です。 3つのミューテックス。use_count()5以下の場合、いずれか1つをshared_ptrコピー/破棄すると、同じポインターの所有権を共有する他のインスタンスをコピー/破棄すると競合します。ほとんどの更新が互いに離れている非隣接ノードに対するものである場合、使用回数が多いと競合が少なくなる可能性がありますが、一般的な場合はおそらくそうではありません。たくさんのプログラムが使用していますshared_ptr使用回数は1桁です。使用数が多く、ノードで競合がない場合でも、3つのミューテックスをロックし、リストノードを作成/破棄し(ヒープ割り当てが必要な場合があります)、隣接ノードのポインターを更新する必要があるため、アトミックインクリメント/デクリメントははるかに単純であり、アトミック整数の競合にもかかわらず、さらに高速になる可能性があります。

前回、委員会のリフレクターで、shared_ptr参照カウントを使用する必要がなく、リストを使用できると述べたときに、返信を受け取りました。

標準がマルチスレッドを認識していることを考えると、誰かが実際にそれを行っていますか?

および(スレッドセーフ要件に関連して):

参照にリンクされた実装では、それを(効率的に)機能させるのははるかに困難です。可能かもしれませんが、それが可能かどうかさえわかりません。

于 2013-01-13T15:16:14.007 に答える