従来の理由から、生のポインターをスマートポインターに変換する機能が必要なため、侵入型ポインターを使用する必要があります。
しかし、私はブーストのための弱い侵入的なポインターがないことに気づきました。ブーストスレッドリストでそれについての話を見つけましたが、具体的なことは何もありません。
弱い侵入型ポインタのスレッドセーフな実装を知っている人はいますか?
ありがとうリッチ
それは意味がありません。
詳述すると:そうするオブジェクトweak_ptr
の同じインスタンスを指します。スコープ外になると、インスタンスは(事実上0のカウントで)とどまります。これにより、インスタンスは、解放されたオブジェクトを効果的に指していることを確認できます。counter
shared_ptr
shared_ptr
counter
weak_ptr
Intrusive Countingを使用すると、カウンターはオブジェクト内に統合されます。カウントが0に達すると、オブジェクトは通常、リサイクルまたは削除されます...しかし、ポイントは、カウンターが使用できなくなったことです。理論的根拠は、これにより、より効率的なストレージ(1つの単一チャンク)とより高速な(キャッシュの局所性)が可能になるということです。
弱参照カウントが必要で、侵入カウントの利点を気にしない場合は、との組み合わせを使用できshared_ptr
ますweak_ptr
。
アイデアは、オブジェクトからカウンターの関連付けを解除することです。
class Counted
{
// bla
private:
boost::shared_ptr<int> mCounter;
};
これで、弱いハンドルを返すことができます。
class WeakHandle
{
public:
explicit WeakHandle(Counted& c): mCounter(c.mCounter), mObject(&c) {}
bool expired() const { return mCounter.expired(); }
private:
boost::weak_ptr<int> mCounter;
Counted* mObject;
};
ここでは、カウンターの存続期間とオブジェクトの存続期間の関連付けを解除して、オブジェクトの破壊に耐えられるようにします...部分的に。したがって、weak_ptr
効果的に可能にします。
そしてもちろん、これを使用するshared_ptr
とweak_ptr
スレッドセーフになります;)
私は前の答えのどちらも本当に好きではなかったので:
いいえ、実装についてはわかりませんが、可能だと思います。shared_ptrの標準実装は、2つの参照カウントを保持します。1つは「強い」参照用、もう1つは「弱い」参照用、および指示対象へのポインターです。intrusive_ptr実装では、強いカウントをオブジェクトの一部にする必要がありますが、弱いカウントを含めることはできません。したがって、「弱い」intrusive_ptrを作成できるようです。
弱いポインターヘルパーを定義します。
template<class X>
class intrusive_ptr_weak_helper {
long weak_ref_count;
X *target_instance;
};
次に、それを参照カウントの横のオブジェクトに記録します。
struct X {
...
intrusive_ptr_weak_helper *ref_weak_helper;
...
long ref_count;
...
};
Xを構築する場合:
ref_count = 0;
ref_weak_helper = NULL;
「強い」ポインタintrusive_strong_ptrは、削除が行われるまでintrusive_ptrと同じです。強力な参照カウントがゼロになったとき(削除が発生する前):
if (ref_weak_helper != NULL) {
if (ref_weak_helper->weak_ref_count == 0)
delete ref_weak_helper;
else
ref_weak_helper->target_instance = NULL;
}
「弱い」バージョンのintrusive_weak_ptrは、弱いヘルパーへのポインターを記録し、その参照カウントを操作し、target_instanceポインターを介してターゲットオブジェクトにアクセスします。weak_ref_countがゼロに減少すると、target_instanceのステータスによって、ヘルパーが削除されるかどうかが決まります。
多くの詳細が欠落しています(たとえば、同時実行の懸念)が、これはshared_ptrとintrusive_ptrの混合です。これは、主に弱参照パスに余分な作業を追加しながら、intrusive_ptrの基本的な利点(キャッシュの最適化、サードパーティの侵入(強)参照カウントの再利用、強および弱ポインタースタンドインはポインターサイズ)を維持します。
侵入型ポインターの現在の実装は、参照カウンターを使用しています。したがって、オブジェクト削除を削除するとカウンターも削除されるため、weak_intrusive_pointerはオブジェクトが削除されたことを認識しません。
からweak_ptrを取得する必要がある場合はthis
、おそらく検索しboost::enable_shared_from_this<T>
ます。
OpenSceneGraphとその後継であるVulkanSceneGraphには、それぞれref_ptr<>とobserver_ptr<>という名前の侵入型の強いポインターと関連する弱いポインターの包括的な実装があります。
これらのシステムの詳細はわかりませんが、指示対象(Referencedクラスの子孫)が削除されたときに通知される追加のオブジェクトを使用して機能しているようです。弱いポインターは、強いポインターに変換しようとするときに、この3番目のオブジェクトを使用します。
VulkanSceneGraphは、現在開発中の次世代シーングラフであり、OpenSceneGraphを置き換えることを目的としているため、その侵入型ポインターシステムはより高度な実装であると思います。
チェックアウトする価値があります:
https://github.com/vsg-dev/VulkanSceneGraph/blob/master/include/vsg/core/observer_ptr.h