diff --git a/Include/Aurora/Memory/MemoryView.hpp b/Include/Aurora/Memory/MemoryView.hpp index 8a041dc1..205ff54f 100644 --- a/Include/Aurora/Memory/MemoryView.hpp +++ b/Include/Aurora/Memory/MemoryView.hpp @@ -26,6 +26,21 @@ namespace Aurora::Memory // (Consider inverse construction order, for instance, we'd have to always call MemoryView::ResetControlBlock() // in a derived subclass, in order release the pInUseCounter reference before the derived shared members get released) AuSPtr pPinner; // WARNING: as usual, std types don't validate their allocator, and our shared ptrs can be different between binaries! + + ~MemoryControlBlock() + { + this->Release(); + } + + void Release() + { + if (auto pCounter = AuExchange(this->pInUseCounter, nullptr)) + { + AuAtomicSub(pCounter, 1u); + } + + AuResetMember(this->pPinner); + } }; template @@ -216,11 +231,6 @@ namespace Aurora::Memory this->controlBlock.pPinner = pRAIIOwner; } - ~MemoryView() - { - this->ResetControlBlock(); - } - private: template MemoryView(T *start, AuUInt length, const MemoryControlBlock ©Block) @@ -382,11 +392,15 @@ namespace Aurora::Memory return MemoryView(MemoryView(pData.get(), uLength), pData); } - bool CloneSelf() + bool TryCloneSelf(bool bResetOnFailure = true) { auto replacement = Clone(); if (!replacement) { + if (bResetOnFailure) + { + AuResetMember(*this); + } return false; } AuResetMember(*this, replacement); @@ -407,17 +421,6 @@ namespace Aurora::Memory private: MemoryControlBlock controlBlock; - protected: - void ResetControlBlock() - { - if (auto pCounter = AuExchange(this->controlBlock.pInUseCounter, nullptr)) - { - AuAtomicSub(pCounter, 1u); - } - - AuResetMember(this->controlBlock.pPinner); - } - public: bool HasControlBlock() const { @@ -467,6 +470,21 @@ namespace Aurora::Memory #endif } + AuSPtr TryPromoteToSharedViewNoParentNesting(AuSPtr pParent = {}) + { + if (this->HasControlBlock()) + { + return AuMakeShared(*this); + } + + if (pParent) + { + return AuMakeShared(*this, pParent); + } + + return {}; + } + bool TryDemoteFromSharedView(const AuSPtr &pCopy) { if (pCopy && pCopy->HasControlBlock()) @@ -480,6 +498,19 @@ namespace Aurora::Memory } } + bool TryDemoteFromReference(const MemoryView &refCopy) + { + if (refCopy.HasControlBlock()) + { + AuResetMember(*this, refCopy); + return true; + } + else + { + return false; + } + } + void DemoteFromSharedView(const AuSPtr &pCopy) { if (!pCopy) @@ -497,6 +528,39 @@ namespace Aurora::Memory AuResetMember(*this, AuConstReference(*pCopy.get()), pCopy); } } + + AuSPtr ToSharedControlBlock(bool *pbFailed = nullptr) + { + if (pbFailed) + { + *pbFailed = false; + } + + if (this->controlBlock.pInUseCounter) + { + auto pShared = AuMakeShared(); + if (!pShared) + { + if (pbFailed) + { + *pbFailed = true; + } + return {}; + } + + AuAtomicAdd(&this->controlBlock.pInUseCounter, 1u); + pShared->pInUseCounter = this->controlBlock.pInUseCounter; + pShared->pPinner = this->controlBlock.pPinner; + return pShared; + } + + if (this->controlBlock.pPinner) + { + return this->controlBlock.pPinner; + } + + return {}; + } }; using MemoryViewRead = MemoryView;