31 #include "DebugUtilities.h" 32 #include "LockHelper.h" 33 #include "ValidatedCast.h" 34 #include "MemoryAllocator.h" 40 class RefCountersImpl :
public IReferenceCounters
43 inline virtual CounterValueType AddStrongRef()override final
45 VERIFY( m_ObjectState == ObjectState::Alive,
"Attempting to increment strong reference counter for a destroyed or not itialized object!" );
46 VERIFY( m_ObjectWrapperBuffer[0] != 0 && m_ObjectWrapperBuffer[1] != 0,
"Object wrapper is not initialized");
47 return Atomics::AtomicIncrement(m_lNumStrongReferences);
50 inline virtual CounterValueType ReleaseStrongRef()override final
52 VERIFY( m_ObjectState == ObjectState::Alive,
"Attempting to decrement strong reference counter for an object that is not alive" );
53 VERIFY( m_ObjectWrapperBuffer[0] != 0 && m_ObjectWrapperBuffer[1] != 0,
"Object wrapper is not initialized");
56 auto RefCount = Atomics::AtomicDecrement(m_lNumStrongReferences);
57 VERIFY( RefCount >= 0,
"Inconsistent call to ReleaseStrongRef()" );
141 Atomics::Long NumStrongRefs = m_lNumStrongReferences;
142 VERIFY( NumStrongRefs == 0 || NumStrongRefs == 1,
"Num strong references (", NumStrongRefs,
") is expected to be 0 or 1" );
146 ThreadingTools::LockHelper Lock(m_LockFlag);
152 VERIFY_EXPR( m_lNumStrongReferences == 0 && m_ObjectState == ObjectState::Alive );
155 if(m_lNumStrongReferences == 0 && m_ObjectState == ObjectState::Alive)
157 VERIFY(m_ObjectWrapperBuffer[0] != 0 && m_ObjectWrapperBuffer[1] != 0,
"Object wrapper is not initialized");
173 size_t ObjectWrapperBufferCopy[ObjectWrapperBufferSize];
174 for(
size_t i=0; i < ObjectWrapperBufferSize; ++i)
175 ObjectWrapperBufferCopy[i] = m_ObjectWrapperBuffer[i];
177 memset(m_ObjectWrapperBuffer, 0,
sizeof(m_ObjectWrapperBuffer));
179 auto *pWrapper =
reinterpret_cast<ObjectWrapperBase*
>(ObjectWrapperBufferCopy);
189 m_ObjectState = ObjectState::Destroyed;
213 bool bDestroyThis = m_lNumWeakReferences == 0;
225 pWrapper->DestroyObject();
237 inline virtual CounterValueType AddWeakRef()override final
239 return Atomics::AtomicIncrement(m_lNumWeakReferences);
242 inline virtual CounterValueType ReleaseWeakRef()override final
245 ThreadingTools::LockHelper Lock(m_LockFlag);
250 auto NumWeakReferences = Atomics::AtomicDecrement(m_lNumWeakReferences);
251 VERIFY( NumWeakReferences >= 0,
"Inconsistent call to ReleaseWeakRef()" );
293 if( NumWeakReferences == 0 && m_ObjectState == ObjectState::Destroyed )
295 VERIFY_EXPR(m_lNumStrongReferences == 0);
296 VERIFY( m_ObjectWrapperBuffer[0] == 0 && m_ObjectWrapperBuffer[1] == 0,
"Object wrapper must be null");
311 return NumWeakReferences;
314 inline virtual void GetObject(
class IObject **ppObject )
override final 316 if( m_ObjectState != ObjectState::Alive)
335 ThreadingTools::LockHelper Lock(m_LockFlag);
337 auto StrongRefCnt = Atomics::AtomicIncrement(m_lNumStrongReferences);
353 if( m_ObjectState == ObjectState::Alive && StrongRefCnt > 1 )
355 VERIFY( m_ObjectWrapperBuffer[0] != 0 && m_ObjectWrapperBuffer[1] != 0,
"Object wrapper is not initialized");
359 auto *pWrapper =
reinterpret_cast<ObjectWrapperBase*
>(m_ObjectWrapperBuffer);
360 pWrapper->QueryInterface(Diligent::IID_Unknown, ppObject);
362 Atomics::AtomicDecrement(m_lNumStrongReferences);
365 inline virtual CounterValueType GetNumStrongRefs()const override final
367 return m_lNumStrongReferences;
370 inline virtual CounterValueType GetNumWeakRefs()const override final
372 return m_lNumWeakReferences;
376 template<
typename AllocatorType,
typename ObjectType>
377 friend class MakeNewRCObj;
379 RefCountersImpl()noexcept
381 m_lNumStrongReferences = 0;
382 m_lNumWeakReferences = 0;
384 memset(m_ObjectWrapperBuffer, 0,
sizeof(m_ObjectWrapperBuffer));
388 class ObjectWrapperBase
391 virtual void DestroyObject() = 0;
392 virtual void QueryInterface(
const Diligent::INTERFACE_ID &iid, IObject **ppInterface )=0;
395 template<
typename ObjectType,
typename AllocatorType>
396 class ObjectWrapper :
public ObjectWrapperBase
399 ObjectWrapper(ObjectType *pObject, AllocatorType *pAllocator)noexcept :
401 m_pAllocator(pAllocator)
403 virtual void DestroyObject()override final
407 m_pObject->~ObjectType();
408 m_pAllocator->Free(m_pObject);
415 virtual void QueryInterface(
const Diligent::INTERFACE_ID &iid, IObject **ppInterface )
override final 417 return m_pObject->QueryInterface(iid, ppInterface);
423 ObjectType*
const m_pObject;
424 AllocatorType *
const m_pAllocator;
427 template<
typename ObjectType,
typename AllocatorType>
428 void Attach(ObjectType *pObject, AllocatorType *pAllocator)
430 VERIFY(m_ObjectState == ObjectState::NotInitialized,
"Object has already been attached");
431 static_assert(
sizeof(ObjectWrapper<ObjectType, AllocatorType>) ==
sizeof(m_ObjectWrapperBuffer),
"Unexpected object wrapper size");
432 new(m_ObjectWrapperBuffer) ObjectWrapper<ObjectType, AllocatorType>(pObject, pAllocator);
433 m_ObjectState = ObjectState::Alive;
443 VERIFY( m_lNumStrongReferences == 0 && m_lNumWeakReferences == 0,
444 "There exist outstanding references to the object being destroyed" );
448 RefCountersImpl(
const RefCountersImpl&) =
delete;
449 RefCountersImpl(RefCountersImpl&&) =
delete;
450 RefCountersImpl& operator = (
const RefCountersImpl&) =
delete;
451 RefCountersImpl& operator = (RefCountersImpl&&) =
delete;
453 static constexpr
size_t ObjectWrapperBufferSize =
sizeof(ObjectWrapper<IObject, IMemoryAllocator>) /
sizeof(
size_t);
454 size_t m_ObjectWrapperBuffer[ObjectWrapperBufferSize];
455 Atomics::AtomicLong m_lNumStrongReferences;
456 Atomics::AtomicLong m_lNumWeakReferences;
457 ThreadingTools::LockFlag m_LockFlag;
458 enum class ObjectState : Int32
464 volatile ObjectState m_ObjectState = ObjectState::NotInitialized;
469 template<
typename Base>
473 using CounterValueType = IReferenceCounters::CounterValueType;
476 m_pRefCounters( ValidatedCast<RefCountersImpl>(pRefCounters) )
507 inline virtual IReferenceCounters* GetReferenceCounters()
const override final 509 VERIFY_EXPR(m_pRefCounters !=
nullptr);
510 return m_pRefCounters;
513 inline virtual CounterValueType AddRef()
override final 515 VERIFY_EXPR(m_pRefCounters !=
nullptr);
518 return m_pRefCounters->AddStrongRef();
521 inline virtual CounterValueType Release()
override 523 VERIFY_EXPR(m_pRefCounters !=
nullptr);
526 return m_pRefCounters->ReleaseStrongRef();
530 template<
typename AllocatorType,
typename ObjectType>
531 friend class MakeNewRCObj;
533 friend class RefCountersImpl;
540 void operator delete(
void *ptr)
542 delete[]
reinterpret_cast<Uint8*
>(ptr);
545 template<
typename ObjectAllocatorType>
546 void operator delete(
void *ptr, ObjectAllocatorType &Allocator,
const Char* dbgDescription,
const char* dbgFileName,
const Int32 dbgLineNumber)
548 return Allocator.Free(ptr);
554 void*
operator new(
size_t Size)
556 return new Uint8[Size];
559 template<
typename ObjectAllocatorType>
560 void*
operator new(
size_t Size, ObjectAllocatorType &Allocator,
const Char* dbgDescription,
const char* dbgFileName,
const Int32 dbgLineNumber)
562 return Allocator.Allocate(Size, dbgDescription, dbgFileName, dbgLineNumber);
569 RefCountersImpl *
const m_pRefCounters;
573 template<
typename ObjectType,
typename AllocatorType = IMemoryAllocator>
577 MakeNewRCObj(AllocatorType &Allocator,
const Char* dbgDescription,
const char* dbgFileName,
const Int32 dbgLineNumber, IObject* pOwner =
nullptr)noexcept :
578 m_pAllocator(&Allocator),
580 m_dbgDescription(dbgDescription),
581 m_dbgFileName(dbgFileName),
582 m_dbgLineNumber(dbgLineNumber)
586 MakeNewRCObj(IObject* pOwner =
nullptr)noexcept :
587 m_pAllocator(
nullptr),
589 m_dbgDescription(
nullptr),
590 m_dbgFileName(
nullptr),
594 MakeNewRCObj(
const MakeNewRCObj&) =
delete;
595 MakeNewRCObj(MakeNewRCObj&&) =
delete;
596 MakeNewRCObj& operator=(
const MakeNewRCObj&) =
delete;
597 MakeNewRCObj& operator=(MakeNewRCObj&&) =
delete;
599 template<
typename ... CtorArgTypes>
600 ObjectType* operator() (CtorArgTypes&& ... CtorArgs)
602 RefCountersImpl *pNewRefCounters =
nullptr;
603 IReferenceCounters *pRefCounters =
nullptr;
604 if(m_pOwner !=
nullptr)
605 pRefCounters = m_pOwner->GetReferenceCounters();
610 pNewRefCounters =
new RefCountersImpl();
611 pRefCounters = pNewRefCounters;
613 ObjectType *pObj =
nullptr;
619 pObj =
new(*m_pAllocator, m_dbgDescription, m_dbgFileName, m_dbgLineNumber) ObjectType(pRefCounters, std::forward<CtorArgTypes>(CtorArgs)... );
621 pObj =
new ObjectType( pRefCounters, std::forward<CtorArgTypes>(CtorArgs)... );
622 if(pNewRefCounters !=
nullptr)
623 pNewRefCounters->Attach<ObjectType, AllocatorType>(pObj, m_pAllocator);
627 if(pNewRefCounters !=
nullptr)
628 pNewRefCounters->SelfDestroy();
635 AllocatorType*
const m_pAllocator;
636 IObject*
const m_pOwner;
637 const Char*
const m_dbgDescription;
638 const char*
const m_dbgFileName;
639 const Int32 m_dbgLineNumber;
642 #define NEW_RC_OBJ(Allocator, Desc, Type, ...) MakeNewRCObj<Type, typename std::remove_reference<decltype(Allocator)>::type>(Allocator, Desc, __FILE__, __LINE__, ##__VA_ARGS__) Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
Base class for all reference counting objects.
Definition: RefCountedObjectImpl.h:470