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

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>();

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

我的问题是:

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

2)有没有优化 clWeakPtr::Lock() 的方法?

1个回答

4

1) 看起来确实安全,但任何对图形的修改都会与 LPtr::GetObjectsGraphPtrWrapper 产生一些争用。

2) 读写锁可以帮助解决问题,至少你可以同时调用几个 Lock()

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


如果您可以访问boost,您可以使用boost::shared_mutex(如https://dev59.com/bHVC5IYBdhLWcg3wlyQo中所示,那里也有Windows的响应),对于pthreads(https://dev59.com/FF7Va4cB1Zd3GeqPLqa1),您的LPtr :: GetObjectsGraphPtrWrapper将是读者,实际修改图形的函数将是写者。请注意,它仅会保护图形和对象的存在,而不是对象内容(除非在修改对象之前进行写锁定,这取决于您的需求)。 - armel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接