在C ++中实现弱的侵入式指针

时间:2012-11-12 12:12:18

标签: c++ smart-pointers weak-references

  

弱指针就像智能指针,除了来自弱指的引用   指针不会阻止垃圾收集,而弱指针也必须如此   在使用之前检查它们的有效性。

在我们的项目(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>();

GenerationsEnvironment范围内是全局的,并且每次实例化新对象时都会原子递增。

我的问题是:

1)实现像这样的弱引用是否安全?

2)有没有办法优化clWeakPtr::Lock()

1 个答案:

答案 0 :(得分:4)

1)确实似乎很安全,但对图表的任何修改都会与LPtr::GetObjectsGraphPtrWrapper

发生争执

2)读写锁可以提供帮助,至少你可以并行调用多个Lock()

你的解决方案的问题在于它击败了非侵入性弱指针带来的局部性。 根据并发级别,它可能会成为一个问题,因为每次调用Lock()都会阻止任何对象创建,以及任何其他没有读写锁定的Lock()调用。