11

弱ポインタ​​ーはスマートポインターに似ていますが、弱ポインタ​​ーからの参照がガベージコレクションを妨げないことと、弱ポインタ​​ーを使用する前に有効性をチェックする必要があることを除けば。

私たちのプロジェクト(Linderdaum Engine http://www.linderdaum.com)では、侵入型ポインターを使用しています。循環参照と孤立の島を回避するために、次の方法で弱い侵入型ポインターを実装しました。

namespace LPtr
{
    clPtr<iObject> GetObjectsGraphPtrWrapper( sEnvironment* Env, iObject* Obj, size_t Generation );
};

/// Intrusive weak smart pointer
template <class T> class clWeakPtr
{
public:
    /// default constructor
    clWeakPtr(): Env( NULL ), FObject( NULL ), FGeneration( 0 ) {}
    explicit clWeakPtr( T* Ptr )
     : Env( Ptr ? Ptr->Env : NULL )
     , FObject( Ptr )
     , FGeneration( Ptr ? Ptr->FGeneration : 0 ) {}
    explicit clWeakPtr( const clPtr<T>& Ptr )
     : Env( Ptr ? Ptr->Env : NULL )
     , FObject( Ptr.GetInternalPtr() )
     , FGeneration( Ptr ? Ptr->FGeneration : 0 ) {}
    clPtr<T> Lock() const
    {
        clPtr<iObject> P = LPtr::GetObjectsGraphPtrWrapper( Env, FObject, FGeneration );

        return P.DynamicCast<T>();
    }
private:
    sEnvironment* Env;
    T*            FObject;
    size_t        FGeneration;
};

GetObjectsGraphPtrWrapper前方宣言のためだけにここにあり、大まかにこれを行います:

LMutex Lock( &FObjectsGraphMutex );

clObjectsGraph::const_iterator i = std::find( Env->ObjectsGraph.begin(), Env->ObjectsGraph.end(), Obj );

if ( i == Env->ObjectsGraph.end() ) return clPtr<iObject>();

bool IsSame  = Obj->FGeneration == Generation;
bool IsAlive = Obj->GetReferenceCounter() > 0;

return  ( IsSame && IsAlive ) ? clPtr<iObject>( Obj ) : clPtr<iObject>();

Generationの範囲はグローバルでありsEnvironment、新しいオブジェクトがインスタンス化されるたびにアトミックにインクリメントされます。

私の質問は次のとおりです。

1)このような弱参照を実装しても安全ですか?

2)最適化する方法はありますclWeakPtr::Lock()か?

4

1 に答える 1

4

1)確かに安全なようですが、グラフを変更すると、次のような競合が発生します。LPtr::GetObjectsGraphPtrWrapper

2)読み取​​り/書き込みロックが役立つ可能性があります。少なくとも、複数Lock()を並行して呼び出すことができます。

ソリューションの問題は、邪魔にならない弱いポインターがもたらす局所性を打ち負かすことです。同時実行レベルによっては、を呼び出すたびにオブジェクトの作成や、読み取り/書き込みロックのないLock()他の呼び出しが妨げられるため、問題になる可能性があります。Lock()

于 2012-11-13T20:35:55.383 に答える