C++ 在C+中实现弱入侵指针+;
弱指针与智能指针类似,只是来自弱指针的引用 指针不能阻止垃圾收集,弱指针必须 在使用前检查其有效性 在我们的项目(Linderdaum引擎)中,我们使用入侵指针。为了避免循环引用和隔离岛,我们通过以下方式实现了弱入侵指针: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
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>();