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

C++ 在C+中实现弱入侵指针+;,c++,smart-pointers,weak-references,C++,Smart Pointers,Weak References,弱指针与智能指针类似,只是来自弱指针的引用 指针不能阻止垃圾收集,弱指针必须 在使用前检查其有效性 在我们的项目(Linderdaum引擎)中,我们使用入侵指针。为了避免循环引用和隔离岛,我们通过以下方式实现了弱入侵指针: namespace LPtr { clPtr<iObject> GetObjectsGraphPtrWrapper( sEnvironment* Env, iObject* Obj, size_t Generation ); }; /// Intrusi

弱指针与智能指针类似,只是来自弱指针的引用 指针不能阻止垃圾收集,弱指针必须 在使用前检查其有效性

在我们的项目(Linderdaum引擎)中,我们使用入侵指针。为了避免循环引用和隔离岛,我们通过以下方式实现了弱入侵指针:

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;
};
Generation
sEnvironment
的范围内是全局的,并且在每次实例化一个新对象时原子递增

我的问题是:

1) 实现这样的弱引用安全吗

2) 是否有任何方法可以优化
clWeakPtr::Lock()

1)它看起来确实很安全,但是对图形的任何修改都会与
LPtr::getObjectsGraphPtrRapper

2) 读写锁可能会有所帮助,至少您可以并行调用多个
lock()

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

如果您有权访问boost,您可以使用boost::shared_互斥体(如中所示,也有针对Windows的响应)来访问pthreads(),您的LPtr::GetObjectsGraphPtrRapper将是一个读取器,而实际修改图形的函数将是一个编写器。请注意,它将仅保护图形和对象的存在,而不保护对象内容(除非修改对象之前的写锁取决于您的需要)
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>();