弱ポインターはスマートポインターに似ていますが、弱ポインターからの参照がガベージコレクションを妨げないことと、弱ポインターを使用する前に有効性をチェックする必要があることを除けば。
私たちのプロジェクト(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()
か?