Ser*_* K. 11 c++ weak-references smart-pointers
弱指针就像智能指针,除了弱指针的引用不会阻止垃圾收集,弱指针必须在使用之前检查它们的有效性.
在我们的项目中(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;
};
Run Code Online (Sandbox Code Playgroud)
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>();
Run Code Online (Sandbox Code Playgroud)
Generation 是全球性的 sEnvironment每次实例化新对象时,它并且是原子递增的.
我的问题是:
1)实现像这样的弱引用是否安全?
2)有什么方法可以优化clWeakPtr::Lock()?
1)看起来确实安全,但是对图的任何修改都会与LPtr::GetObjectsGraphPtrWrapper
2)读写锁可以提供帮助,至少您可以并行调用Lock()多个
您的解决方案的问题在于它破坏了非侵入性弱指针带来的局部性。根据并发级别,这可能会成为一个问题,因为每次调用都会Lock()阻止任何对象创建以及任何其他Lock()没有读写锁的调用。