Реализация слабых навязчивых указателей в переполнении стека

Слабые указатели похожи на умные указатели, за исключением того, что ссылки со слабых
указатели не мешают сборке мусора, а слабые указатели должны
проверить их действительность, прежде чем они будут использованы.

В нашем проекте (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>();

Generation является глобальным в сфере sEnvironment и атомарно увеличивается каждый раз, когда создается новый объект.

Мои вопросы:

1) Безопасно ли реализовывать подобные слабые ссылки?

2) Есть ли способы оптимизировать clWeakPtr::Lock()?

11

Решение

1) Это кажется действительно безопасным, но любая модификация графика будет иметь некоторые противоречия с LPtr::GetObjectsGraphPtrWrapper

2) может помочь блокировка чтения-записи, по крайней мере, вы сможете вызвать несколько Lock() в параллели

Проблема с вашим решением состоит в том, что он побеждает местность, которую приносят неинтрузивные слабые указатели.
В зависимости от уровня параллелизма, это может стать проблемой, так как каждый вызов Lock() предотвратит любое создание объекта, а также любой другой Lock() вызов без блокировки чтения-записи.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]