33 #include "../../Primitives/interface/Object.h"
34 #include "../../Primitives/interface/MemoryAllocator.h"
35 #include "../../Platforms/interface/Atomics.hpp"
36 #include "../../Platforms/Basic/interface/DebugUtilities.hpp"
49 VERIFY(m_ObjectState == ObjectState::Alive,
"Attempting to increment strong reference counter for a destroyed or not itialized object!");
50 VERIFY(m_ObjectWrapperBuffer[0] != 0 && m_ObjectWrapperBuffer[1] != 0,
"Object wrapper is not initialized");
54 template <
class TPreObjectDestroy>
57 VERIFY(m_ObjectState == ObjectState::Alive,
"Attempting to decrement strong reference counter for an object that is not alive");
58 VERIFY(m_ObjectWrapperBuffer[0] != 0 && m_ObjectWrapperBuffer[1] != 0,
"Object wrapper is not initialized");
62 VERIFY(RefCount >= 0,
"Inconsistent call to ReleaseStrongRef()");
91 VERIFY(NumWeakReferences >= 0,
"Inconsistent call to ReleaseWeakRef()");
133 if (NumWeakReferences == 0 && m_ObjectState == ObjectState::Destroyed)
136 VERIFY(m_ObjectWrapperBuffer[0] == 0 && m_ObjectWrapperBuffer[1] == 0,
"Object wrapper must be null");
151 return NumWeakReferences;
156 if (m_ObjectState != ObjectState::Alive)
193 if (m_ObjectState == ObjectState::Alive && StrongRefCnt > 1)
195 VERIFY(m_ObjectWrapperBuffer[0] != 0 && m_ObjectWrapperBuffer[1] != 0,
"Object wrapper is not initialized");
199 auto* pWrapper =
reinterpret_cast<ObjectWrapperBase*
>(m_ObjectWrapperBuffer);
200 pWrapper->QueryInterface(IID_Unknown, ppObject);
207 return m_lNumStrongReferences;
212 return m_lNumWeakReferences;
216 template <
typename AllocatorType,
typename ObjectType>
221 m_lNumStrongReferences = 0;
222 m_lNumWeakReferences = 0;
223 #ifdef DILIGENT_DEBUG
224 memset(m_ObjectWrapperBuffer, 0,
sizeof(m_ObjectWrapperBuffer));
228 class ObjectWrapperBase
231 virtual void DestroyObject() = 0;
235 template <
typename ObjectType,
typename AllocatorType>
236 class ObjectWrapper :
public ObjectWrapperBase
239 ObjectWrapper(ObjectType* pObject, AllocatorType* pAllocator) noexcept :
241 m_pAllocator{pAllocator}
243 virtual void DestroyObject() override final
247 m_pObject->~ObjectType();
248 m_pAllocator->Free(m_pObject);
255 virtual void QueryInterface(
const INTERFACE_ID& iid, IObject** ppInterface)
override final
257 return m_pObject->QueryInterface(iid, ppInterface);
264 ObjectType*
const m_pObject;
265 AllocatorType*
const m_pAllocator;
268 template <
typename ObjectType,
typename AllocatorType>
269 void Attach(ObjectType* pObject, AllocatorType* pAllocator)
271 VERIFY(m_ObjectState == ObjectState::NotInitialized,
"Object has already been attached");
272 static_assert(
sizeof(ObjectWrapper<ObjectType, AllocatorType>) ==
sizeof(m_ObjectWrapperBuffer),
"Unexpected object wrapper size");
273 new (m_ObjectWrapperBuffer) ObjectWrapper<ObjectType, AllocatorType>(pObject, pAllocator);
274 m_ObjectState = ObjectState::Alive;
277 void TryDestroyObject()
359 #ifdef DILIGENT_DEBUG
362 VERIFY(NumStrongRefs == 0 || NumStrongRefs == 1,
"Num strong references (", NumStrongRefs,
") is expected to be 0 or 1");
373 VERIFY_EXPR(m_lNumStrongReferences == 0 && m_ObjectState == ObjectState::Alive);
376 if (m_lNumStrongReferences == 0 && m_ObjectState == ObjectState::Alive)
378 VERIFY(m_ObjectWrapperBuffer[0] != 0 && m_ObjectWrapperBuffer[1] != 0,
"Object wrapper is not initialized");
394 size_t ObjectWrapperBufferCopy[ObjectWrapperBufferSize];
395 for (
size_t i = 0; i < ObjectWrapperBufferSize; ++i)
396 ObjectWrapperBufferCopy[i] = m_ObjectWrapperBuffer[i];
397 #ifdef DILIGENT_DEBUG
398 memset(m_ObjectWrapperBuffer, 0,
sizeof(m_ObjectWrapperBuffer));
400 auto* pWrapper =
reinterpret_cast<ObjectWrapperBase*
>(ObjectWrapperBufferCopy);
410 m_ObjectState = ObjectState::Destroyed;
434 bool bDestroyThis = m_lNumWeakReferences == 0;
446 pWrapper->DestroyObject();
462 VERIFY(m_lNumStrongReferences == 0 && m_lNumWeakReferences == 0,
463 "There exist outstanding references to the object being destroyed");
468 RefCountersImpl (
const RefCountersImpl&) =
delete;
469 RefCountersImpl (RefCountersImpl&&) =
delete;
470 RefCountersImpl& operator = (
const RefCountersImpl&) =
delete;
471 RefCountersImpl& operator = (RefCountersImpl&&) =
delete;
474 struct IObjectStub :
public IObject
476 virtual ~IObjectStub() = 0;
481 static constexpr
size_t ObjectWrapperBufferSize =
sizeof(ObjectWrapper<IObjectStub, IMemoryAllocator>) /
sizeof(
size_t);
483 size_t m_ObjectWrapperBuffer[ObjectWrapperBufferSize];
487 enum class ObjectState :
Int32
493 volatile ObjectState m_ObjectState = ObjectState::NotInitialized;
498 template <
typename Base>
502 template <
typename... BaseCtorArgTypes>
505 Base {std::forward<BaseCtorArgTypes>(BaseCtorArgs)...},
506 m_pRefCounters{ValidatedCast<RefCountersImpl>(pRefCounters) }
541 return m_pRefCounters;
560 template <
class TPreObjectDestroy>
568 template <
typename AllocatorType,
typename ObjectType>
578 void operator delete(
void* ptr)
580 delete[]
reinterpret_cast<Uint8*
>(ptr);
583 template <
typename ObjectAllocatorType>
584 void operator delete(
void* ptr, ObjectAllocatorType& Allocator,
const Char* dbgDescription,
const char* dbgFileName,
const Int32 dbgLineNumber)
586 return Allocator.Free(ptr);
592 void*
operator new(
size_t Size)
594 return new Uint8[Size];
597 template <
typename ObjectAllocatorType>
598 void*
operator new(
size_t Size, ObjectAllocatorType& Allocator,
const Char* dbgDescription,
const char* dbgFileName,
const Int32 dbgLineNumber)
600 return Allocator.Allocate(Size, dbgDescription, dbgFileName, dbgLineNumber);
611 template <
typename ObjectType,
typename AllocatorType = IMemoryAllocator>
617 m_pAllocator{&Allocator},
619 #ifdef DILIGENT_DEVELOPMENT
620 , m_dvpDescription{Description}
621 , m_dvpFileName {FileName }
622 , m_dvpLineNumber {LineNumber }
630 m_pAllocator {
nullptr},
632 #ifdef DILIGENT_DEVELOPMENT
633 , m_dvpDescription{
nullptr}
634 , m_dvpFileName {
nullptr}
635 , m_dvpLineNumber {0 }
647 template <
typename... CtorArgTypes>
652 if (m_pOwner !=
nullptr)
659 pRefCounters = pNewRefCounters;
661 ObjectType* pObj =
nullptr;
664 #ifndef DILIGENT_DEVELOPMENT
665 static constexpr
const char* m_dvpDescription =
"<Unavailable in release build>";
666 static constexpr
const char* m_dvpFileName =
"<Unavailable in release build>";
667 static constexpr
Int32 m_dvpLineNumber = -1;
672 pObj =
new (*m_pAllocator, m_dvpDescription, m_dvpFileName, m_dvpLineNumber) ObjectType(pRefCounters, std::forward<CtorArgTypes>(CtorArgs)...);
674 pObj =
new ObjectType(pRefCounters, std::forward<CtorArgTypes>(CtorArgs)...);
675 if (pNewRefCounters !=
nullptr)
676 pNewRefCounters->Attach<ObjectType, AllocatorType>(pObj, m_pAllocator);
680 if (pNewRefCounters !=
nullptr)
681 pNewRefCounters->SelfDestroy();
688 AllocatorType*
const m_pAllocator;
691 #ifdef DILIGENT_DEVELOPMENT
692 const Char*
const m_dvpDescription;
693 const char*
const m_dvpFileName;
694 Int32 const m_dvpLineNumber;
698 #define NEW_RC_OBJ(Allocator, Desc, Type, ...) MakeNewRCObj<Type, typename std::remove_reference<decltype(Allocator)>::type>(Allocator, Desc, __FILE__, __LINE__, ##__VA_ARGS__)