diff --git a/Include/auROXTL/AU_MACROS.hpp b/Include/auROXTL/AU_MACROS.hpp index 2ea227e..e8f0b43 100644 --- a/Include/auROXTL/AU_MACROS.hpp +++ b/Include/auROXTL/AU_MACROS.hpp @@ -62,18 +62,18 @@ \ struct CppDeleter ## name \ { \ - inline void operator()(type *t) \ + inline void operator()(type *t) const \ { \ if (!t) return; \ name ## Release(t); \ } \ }; \ \ - using name ## Unique_t = AURORA_RUNTIME_AU_UNIQUE_PTR; \ + using name ## Unique_t = AuUPtr; \ template \ name ## Unique_t name ## Unique(T &&... args) \ { \ - return name ## Unique_t(name ## New(AuForward(args)...)); \ + return name ## Unique_t(name ## New(AuForward(args)...), name ## Release); \ } \ \ using name ## Shared_t = AuSPtr; \ diff --git a/Include/auROXTL/AU_Z.hpp b/Include/auROXTL/AU_Z.hpp index 431f3b6..dd450e9 100644 --- a/Include/auROXTL/AU_Z.hpp +++ b/Include/auROXTL/AU_Z.hpp @@ -90,5 +90,15 @@ #define _AURORA_AVOID_EXTREMLY_DUMB_STL_TYPES // TODO: #if !defined(_AURORA_NULLEXPT_BRANCH) -#define _AURORA_NULLEXPT_BRANCH +//#define _AURORA_NULLEXPT_BRANCH +#endif + +#if !defined(AURORA_ROXTL_HAS_RUNTIME) + // AURORA_ENGINE_KERNEL - static or local translation unit + // _AUHAS_AURORARUNTIME - standard pipeline macro for including a product by the name AuroraRuntime + #if defined(AURORA_ENGINE_KERNEL) || (defined(_AUHAS_AURORARUNTIME) && _AUHAS_AURORARUNTIME == 1) + #define AURORA_ROXTL_HAS_RUNTIME 1 + #else + #define AURORA_ROXTL_HAS_RUNTIME 0 + #endif #endif \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auDummyHeap.hpp b/Include/auROXTL/MemoryModel/auDummyHeap.hpp new file mode 100755 index 0000000..e973b82 --- /dev/null +++ b/Include/auROXTL/MemoryModel/auDummyHeap.hpp @@ -0,0 +1 @@ +// TODO: \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auDummyHeap.ipp b/Include/auROXTL/MemoryModel/auDummyHeap.ipp new file mode 100755 index 0000000..e973b82 --- /dev/null +++ b/Include/auROXTL/MemoryModel/auDummyHeap.ipp @@ -0,0 +1 @@ +// TODO: \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auHeap.hpp b/Include/auROXTL/MemoryModel/auHeap.hpp new file mode 100755 index 0000000..7041886 --- /dev/null +++ b/Include/auROXTL/MemoryModel/auHeap.hpp @@ -0,0 +1,158 @@ +/*** + Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auHeap.hpp + File: Heap.hpp + Date: 2021-6-9 + Author: Reece + Note: Moved from Runtime to ROXTL + Note: The intention is that the runtime will still implement all the relevant heaps. + However, we should provide one AuDummyHeap that proxies the intrin memory allocations (AuMemory::__FAlloc, AuMemory::__Free, AuMemory::__SizeOf). +***/ +#pragma once + +/** + * Note: The following public global aliases exists for heap and/or global process heap based allocations: + * + * AuHUPOf_t AuNewClassArrayUnique([pHeap, ]uElements, ...) + * AuSPtr AuNewClassArray([pHeap, ]uElements, ...) + * AuHUPOf_t AuNewClassUnique([pHeap, ] ...) + * AuSPtr AuNewClass([pHeap, ] ...) + * AuHUPOf_t AuNullHeapPointer() + */ + +struct AuHeap +{ + virtual AuSPtr AllocateDivision(AuUInt32 heap, AuUInt32 alignment = 32) = 0; + virtual AuUInt GetChunkSize(const void *pHead) = 0; + virtual AuHeapStats & GetStats() = 0; + + virtual void WalkHeap(bool(*fCallback)(void *, void *), void *pSecondArg) = 0; + + /// Potentially slower, zero allocate + template + T ZAlloc(AuUInt uLength); + + /// POD zero allocation + template + T ZAlloc(AuUInt uLength, AuUInt uAlignment); + + /// POD zero allocation + template + T *ZAlloc(); + + /// POD array, zero allocation + template + T *NewArray(AuUInt uLength); + + /// POD array, zero allocation + template + T *NewArray(AuUInt uLength, AuUInt uAlignment); + + /// Fast, POD, non-zeroing allocation + template + T FAlloc(AuUInt uLength); + + /// Fast, POD, non-zeroing allocation + template + T FAlloc(AuUInt uLength, AuUInt uAlignment); + + /// Fast, POD, non-zeroing allocation + template + T *FAlloc(); + +// Reallocs + + /// POD, zero-based expansion or reallocation + template + T ZRealloc(T pHead, AuUInt uLength); + + /// POD, zero-based expansion or reallocation + template + T ZRealloc(T pHead, AuUInt uLength, AuUInt uAlignment); + + /// POD, expansion or reallocation + template + T FRealloc(T pHead, AuUInt uLength); + + /// POD, expansion or reallocation + template + T FRealloc(T pHead, AuUInt uLength, AuUInt uAlignment); + + /// Free + template + void Free(T pHead); + +protected: + + template + static void DeleteThat(T *pThat); + + template + static void DeleteThatArray(T *pThat); + + template + static void DeleteThatArray2(T *pThat); + + template + static void DeleteThatCastedOnce(T *pThat); + + template + static void RetardedSpecWrittenByRetards(T *pThat); + +public: + + template + AuSPtr NewClass(Args &&...args); + + // note: callers can use AuHUPOf_t pUniquePointer = AuNullHeapPointer() + // update: no longer required with memory model update 2024/09 + // AuHUPOf_t or AuUPtr will do + + template + AuUPtr)> NewClassUnique(Args &&...args); + + template + AuSPtr NewClassArray(AuUInt uElements, Args &&... fillCtr); + + // note: despite dtor awareness, this is intended for allocating POD arrays of uAlignment + // this is used by the memory views clone routine. + template + AuSPtr NewClassArray2(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr); + + // note: callers can use AuHUPOf_t pUniquePointer = AuNullHeapPointer() + // update: no longer required with memory model update 2024/09 + // AuHUPOf_t or AuUPtr will do + + template + AuUPtr)> NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr); + + template + AuUPtr)> NewClassArray2Unique(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr); + + template + cstatic AuUPtr)> NullUniquePointer(); + + template + cstatic AuUPtr)> CastPointer(AuUPtr)> &&pInPointer); + + template + using HUPOf_t = AuUPtr)>; + +protected: + friend struct AuHeapAccessor; + friend struct Aurora::Memory::ProxyHeap; + + virtual AuSPtr GetSelfReference() = 0; // may return empty/default. not all heaps are sharable. + virtual AuHeap *GetSelfReferenceRaw() = 0; + + virtual AU_ALLOC void *_ZAlloc(AuUInt uLength) = 0; + virtual AU_ALLOC void *_ZAlloc(AuUInt uLength, AuUInt uAlignment) = 0; + virtual AU_ALLOC void *_FAlloc(AuUInt uLength) = 0; + virtual AU_ALLOC void *_FAlloc(AuUInt uLength, AuUInt uAlignment) = 0; + virtual AU_ALLOC void *_ZRealloc(void *pBase, AuUInt uLength, AuUInt uAlign) = 0; + virtual AU_ALLOC void *_ZRealloc(void *pBase, AuUInt uLength) = 0; + virtual AU_ALLOC void *_FRealloc(void *pBase, AuUInt uLength, AuUInt uAlign) = 0; + virtual AU_ALLOC void *_FRealloc(void *pBase, AuUInt uLength) = 0; + virtual void _Free(void* pBase) = 0; +}; diff --git a/Include/auROXTL/MemoryModel/auHeap.ipp b/Include/auROXTL/MemoryModel/auHeap.ipp new file mode 100755 index 0000000..6eceb6e --- /dev/null +++ b/Include/auROXTL/MemoryModel/auHeap.ipp @@ -0,0 +1,590 @@ +/*** + Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: AuHeap.ipp + File: Heap.inl + Date: 2024-7-14 + Date: 2021-6-9 + Author: Reece + Note: moved from Runtime to ROXTL +***/ +#pragma once + +template +T AuHeap::ZAlloc(AuUInt uLength) +{ + if constexpr (AuIsVoid_v>) + { + return reinterpret_cast(_ZAlloc(uLength)); + } + else + { + return reinterpret_cast(_ZAlloc(uLength, alignof(AuRemovePointer_t))); + } +} + +template +T AuHeap::ZAlloc(AuUInt uLength, AuUInt uAlignment) +{ + return reinterpret_cast(_ZAlloc(uLength, uAlignment)); +} + +template +T *AuHeap::ZAlloc() +{ + return reinterpret_cast(_ZAlloc(sizeof(T), alignof(T))); +} + +template +T *AuHeap::NewArray(AuUInt uLength) +{ + return ZAlloc(uLength * sizeof(T), alignof(T)); +} + +template +T *AuHeap::NewArray(AuUInt uLength, AuUInt uAlignment) +{ + return ZAlloc(uLength * sizeof(T), uAlignment); +} + +template +T AuHeap::FAlloc(AuUInt uLength) +{ + if constexpr (AuIsVoid_v>) + { + return reinterpret_cast(_FAlloc(uLength)); + } + else + { + return reinterpret_cast(_FAlloc(uLength, alignof(AuRemovePointer_t))); + } +} + +template +T AuHeap::FAlloc(AuUInt uLength, AuUInt uAlignment) +{ + return reinterpret_cast(_FAlloc(uLength, uAlignment)); +} + +template +T *AuHeap::FAlloc() +{ + return reinterpret_cast(_FAlloc(sizeof(T), alignof(T))); +} + +// Reallocs +template +T AuHeap::ZRealloc(T pHead, AuUInt uLength) +{ + if constexpr (AuIsVoid_v>) + { + return reinterpret_cast(_ZRealloc(reinterpret_cast(pHead), uLength)); + } + else + { + return reinterpret_cast(_ZRealloc(reinterpret_cast(pHead), uLength, alignof(AuRemovePointer_t))); + } +} + +template +T AuHeap::ZRealloc(T pHead, AuUInt uLength, AuUInt uAlignment) +{ + return reinterpret_cast(_ZRealloc(reinterpret_cast(pHead), uLength, uAlignment)); +} + +template +T AuHeap::FRealloc(T pHead, AuUInt uLength) +{ + if constexpr (AuIsVoid_v>) + { + return reinterpret_cast(_FRealloc(reinterpret_cast(pHead), uLength)); + } + else + { + return reinterpret_cast(_FRealloc(reinterpret_cast(pHead), uLength, alignof(AuRemovePointer_t))); + } +} + +template +T AuHeap::FRealloc(T pHead, AuUInt uLength, AuUInt uAlignment) +{ + return reinterpret_cast(_FRealloc(reinterpret_cast(pHead), uLength, uAlignment)); +} + +// Free +template +void AuHeap::Free(T pHead) +{ + _Free(reinterpret_cast(pHead)); +} + +template +void AuHeap::DeleteThat(T *pThat) +{ + static const auto kAlignment = AuMax(alignof(T), sizeof(void *)); + + if constexpr (AuIsClass_v && + !AuIsTriviallyDestructible_v) + { + pThat->~T(); + } + + auto &pAuHeap = *(AuHeap **)(((char *)pThat) - kAlignment); + pAuHeap->_Free(&pAuHeap); +} + +template +void AuHeap::DeleteThatArray(T *pThat) +{ + static const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2); + + auto pVoids = (void **)(((char *)pThat) - kAlignment); + auto pAuHeap = (AuHeap *)pVoids[0]; + auto uLength = (AuUInt)pVoids[1]; + + if constexpr (AuIsClass_v && + !AuIsTriviallyDestructible_v) + { + for (AU_ITERATE_N(i, uLength)) + { + auto &refElement = pThat[i]; + refElement.~T(); + } + } + + pAuHeap->_Free(pVoids); +} + +template +void AuHeap::DeleteThatArray2(T *pThat) +{ + auto pBase = ((void **)pThat)[-1]; + + auto pVoids = (void **)pBase; + auto pAuHeap = (AuHeap *)pVoids[0]; + auto uLength = (AuUInt)pVoids[1]; + + if constexpr (AuIsClass_v && + !AuIsTriviallyDestructible_v) + { + for (AU_ITERATE_N(i, uLength)) + { + auto &refElement = pThat[i]; + refElement.~T(); + } + } + + pAuHeap->_Free(pVoids); +} +template +void AuHeap::DeleteThatCastedOnce(T *pThat) +{ + static const auto kAlignment = AuMax(alignof(Z), sizeof(void *)); + + auto pBaseClass = AuStaticCast(pThat); + + if constexpr (AuIsClass_v && + !AuIsTriviallyDestructible_v) + { + pBaseClass->~Z(); + } + + auto &pAuHeap = *(AuHeap **)(((char *)pBaseClass) - kAlignment); + pAuHeap->_Free(&pAuHeap); +} + +template +void AuHeap::RetardedSpecWrittenByRetards(T *pThat) +{ + +} + +template +AuSPtr AuHeap::NewClass(Args &&...args) +{ + static const auto kAlignment = AuMax(alignof(T), sizeof(void *)); + AuUInt8 *pPtr; + +#if defined(AURORA_PROXYHEAP_REF_BASE_UAF) + auto pThat = this->GetSelfReferenceRaw(); + if (!pThat) + { + pThat = this; + } +#else + auto pThat = this; +#endif + + if constexpr (AuIsClass_v && + !AuIsTriviallyConstructible_v) + { + pPtr = pThat->FAlloc(sizeof(T) + kAlignment, kAlignment); + if (pPtr) + { + new (pPtr + kAlignment) T(AuForward(args)...); + } + } + else + { + pPtr = pThat->ZAlloc(sizeof(T) + kAlignment, kAlignment); + } + + if (!pPtr) + { + return {}; + } + + *(void **)pPtr = pThat; + + auto pTThat = (T *)(pPtr + kAlignment); + AUROXTL_COMMODITY_TRY + { + return AuSPtr(pTThat, &AuHeap::DeleteThat, AuPMRAllocator { this }); + } + AUROXTL_COMMODITY_CATCH + { + AuHeap::DeleteThat(pTThat); + return {}; + } +} + +template +AuUPtr)> AuHeap::NewClassUnique(Args &&...args) +{ + static const auto kAlignment = AuMax(alignof(T), sizeof(void *)); + AuUInt8 *pPtr; + +#if defined(AURORA_PROXYHEAP_REF_BASE_UAF) + auto pThat = this->GetSelfReferenceRaw(); + if (!pThat) + { + pThat = this; + } +#else + auto pThat = this; +#endif + + if constexpr (AuIsClass_v && + !AuIsTriviallyConstructible_v) + { + pPtr = pThat->FAlloc(sizeof(T) + kAlignment, kAlignment); + if (pPtr) + { + new (pPtr + kAlignment) T(AuForward(args)...); + } + } + else + { + pPtr = pThat->ZAlloc(sizeof(T) + kAlignment, kAlignment); + } + + if (!pPtr) + { + return AuUPtr)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards); + } + + *(void **)pPtr = pThat; + + if constexpr (AuIsSame_v) + { + return AuUPtr)>((T *)(pPtr + kAlignment), &AuHeap::DeleteThat); + } + else + { + return AuHeap::CastPointer(AuMove(AuUPtr)>((T *)(pPtr + kAlignment), &AuHeap::DeleteThat))); + } +} + +template +AuSPtr AuHeap::NewClassArray(AuUInt uElements, Args &&... fillCtr) +{ + const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2); + AuUInt8 *pPtr; + + if (!uElements) + { + return {}; + } + + +#if defined(AURORA_PROXYHEAP_REF_BASE_UAF) + auto pThat = this->GetSelfReferenceRaw(); + if (!pThat) + { + pThat = this; + } +#else + auto pThat = this; +#endif + + if constexpr (AuIsClass_v && + !AuIsTriviallyConstructible_v) + { + if (bool(pPtr = pThat->FAlloc((sizeof(T) * uElements) + kAlignment, kAlignment))) + { + for (AU_ITERATE_N(i, uElements)) + { + new (pPtr + kAlignment + (sizeof(T) * i)) T(AuForward(fillCtr)...); + } + } + } + else + { + if (bool(pPtr = pThat->ZAlloc((sizeof(T) * uElements) + kAlignment, kAlignment))) + { + if constexpr (sizeof...(Args) != 0) + { + #if defined(AURT_AuHeap_NO_STL) + static_assert(false); + #else + auto pElements = (T *)(pPtr + kAlignment); + std::fill(pElements, pElements + uElements, AuForward(fillCtr)...); + #endif + } + } + } + + if (!pPtr) + { + return {}; + } + + auto pVoids = (void **)pPtr; + pVoids[0] = pThat; + pVoids[1] = (void *)uElements; + + auto pTThat = (T *)(pPtr + kAlignment); + AUROXTL_COMMODITY_TRY + { + return AuSPtr(pTThat, &AuHeap::DeleteThatArray, AuPMRAllocator { this }); + } + AUROXTL_COMMODITY_CATCH + { + AuHeap::DeleteThatArray(pTThat); + return {}; + } +} + +template +AuSPtr AuHeap::NewClassArray2(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr) +{ + const auto kAlignment = AuMax(uAlignment, sizeof(void *) * 4); + AuUInt8 *pPtr; + + if (!uElements) + { + return {}; + } + +#if defined(AURORA_PROXYHEAP_REF_BASE_UAF) + auto pThat = this->GetSelfReferenceRaw(); + if (!pThat) + { + pThat = this; + } +#else + auto pThat = this; +#endif + + if constexpr (AuIsClass_v && + !AuIsTriviallyConstructible_v) + { + if (bool(pPtr = pThat->FAlloc((sizeof(T) * uElements) + kAlignment, kAlignment))) + { + for (AU_ITERATE_N(i, uElements)) + { + new (pPtr + kAlignment + (sizeof(T) * i)) T(AuForward(fillCtr)...); + } + } + } + else + { + if (bool(pPtr = pThat->ZAlloc((sizeof(T) * uElements) + kAlignment, kAlignment))) + { + if constexpr (sizeof...(Args) != 0) + { + #if defined(AURT_AuHeap_NO_STL) + static_assert(false); + #else + auto pElements = (T *)(pPtr + kAlignment); + std::fill(pElements, pElements + uElements, AuForward(fillCtr)...); + #endif + } + } + } + + if (!pPtr) + { + return {}; + } + + auto pVoids = (void **)pPtr; + pVoids[0] = pThat; + pVoids[1] = (void *)uElements; + ((void **)(pPtr + kAlignment))[-1] = pPtr; + auto pTThat = (T *)(pPtr + kAlignment); + + AUROXTL_COMMODITY_TRY + { + return AuSPtr(pTThat, &AuHeap::DeleteThatArray2, AuPMRAllocator { this }); + } + AUROXTL_COMMODITY_CATCH + { + AuHeap::DeleteThatArray2(pTThat); + return {}; + } +} + +template +AuUPtr)> AuHeap::NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr) +{ + const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2); + AuUInt8 *pPtr; + + if (!uElements) + { + return AuUPtr)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards); + } + +#if defined(AURORA_PROXYHEAP_REF_BASE_UAF) + auto pThat = this->GetSelfReferenceRaw(); + if (!pThat) + { + pThat = this; + } +#else + auto pThat = this; +#endif + + if constexpr (AuIsClass_v && + !AuIsTriviallyConstructible_v) + { + if (bool(pPtr = pThat->FAlloc((sizeof(T) * uElements) + kAlignment, kAlignment))) + { + for (AU_ITERATE_N(i, uElements)) + { + new (pPtr + kAlignment + (sizeof(T) * i)) T(AuForward(fillCtr)...); + } + } + } + else + { + if (bool(pPtr = pThat->ZAlloc((sizeof(T) * uElements) + kAlignment, kAlignment))) + { + if constexpr (sizeof...(Args) != 0) + { + #if defined(AURT_AuHeap_NO_STL) + static_assert(false); + #else + auto pElements = (T *)(pPtr + kAlignment); + std::fill(pElements, pElements + uElements, AuForward(fillCtr)...); + #endif + } + } + } + + if (!pPtr) + { + return AuUPtr)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards); + } + + auto pVoids = (void **)pPtr; + pVoids[0] = pThat; + pVoids[1] = (void *)uElements; + + return AuUPtr)>((T *)(pPtr + kAlignment), &AuHeap::DeleteThatArray); +} + +template +AuUPtr)> AuHeap::NewClassArray2Unique(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr) +{ + const auto kAlignment = AuMax(uAlignment, sizeof(void *) * 4); + AuUInt8 *pPtr; + + if (!uElements) + { + return AuUPtr)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards); + } + +#if defined(AURORA_PROXYHEAP_REF_BASE_UAF) + auto pThat = this->GetSelfReferenceRaw(); + if (!pThat) + { + pThat = this; + } +#else + auto pThat = this; +#endif + + if constexpr (AuIsClass_v && + !AuIsTriviallyConstructible_v) + { + if (bool(pPtr = pThat->FAlloc((sizeof(T) * uElements) + kAlignment, kAlignment))) + { + for (AU_ITERATE_N(i, uElements)) + { + new (pPtr + kAlignment + (sizeof(T) * i)) T(AuForward(fillCtr)...); + } + } + } + else + { + if (bool(pPtr = pThat->ZAlloc((sizeof(T) * uElements) + kAlignment, kAlignment))) + { + if constexpr (sizeof...(Args) != 0) + { + #if defined(AURT_AuHeap_NO_STL) + static_assert(false); + #else + auto pElements = (T *)(pPtr + kAlignment); + std::fill(pElements, pElements + uElements, AuForward(fillCtr)...); + #endif + } + } + } + + if (!pPtr) + { + return AuUPtr)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards); + } + + auto pVoids = (void **)pPtr; + pVoids[0] = pThat; + pVoids[1] = (void *)uElements; + + ((void **)(pPtr + kAlignment))[-1] = pPtr; + auto pTThat = (T *)(pPtr + kAlignment); + + return AuUPtr)>(pTThat, &AuHeap::DeleteThatArray2); +} + +template +AuUPtr)> AuHeap::NullUniquePointer() +{ + return AuUPtr)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards); +} + +template +AuUPtr)> AuHeap::CastPointer(AuUPtr)> &&pInPointer) +{ + if (!pInPointer) + { + return NullUniquePointer(); + } + else if (pInPointer.get_deleter() == &AuHeap::DeleteThat) + { + return AuUPtr)>(AuStaticCast(pInPointer.release()), &AuHeap::DeleteThatCastedOnce); + } + else + { + return NullUniquePointer(); + } +} + +namespace __audetail +{ + inline AuSPtr AllocateArray(AuHeap *pAuHeap, AuUInt uLength, AuUInt32 uAlignment) + { + return pAuHeap->NewClassArray2(uLength, uAlignment); + } +} \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auHeapAccessor.hpp b/Include/auROXTL/MemoryModel/auHeapAccessor.hpp new file mode 100755 index 0000000..d2363dd --- /dev/null +++ b/Include/auROXTL/MemoryModel/auHeapAccessor.hpp @@ -0,0 +1,23 @@ +/*** + Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auHeapAccessor.hpp + File: Heap.hpp + Date: 2021-6-9 + Author: Reece + Note: moved from Runtime to ROXTL +***/ +#pragma once + +struct AuHeapAccessor +{ + cstatic AuSPtr GetSelfReference(AuHeap *pHeap) + { + return pHeap->GetSelfReference(); + } + + cstatic AuHeap *GetSelfReferenceRaw(AuHeap *pHeap) + { + return pHeap->GetSelfReferenceRaw(); + } +}; diff --git a/Include/auROXTL/MemoryModel/auHeapStats.hpp b/Include/auROXTL/MemoryModel/auHeapStats.hpp new file mode 100755 index 0000000..fcf2561 --- /dev/null +++ b/Include/auROXTL/MemoryModel/auHeapStats.hpp @@ -0,0 +1,22 @@ +/*** + Copyright (C) 2022-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: HeapStats.hpp + Date: 2022-12-07 + Author: Reece + Note: Moved from Runtime +***/ +#pragma once + +struct AuHeapStats +{ + AuUInt uBytesAllocatedLifetime {}; + AuUInt uBytesFreeLifetime {}; + + AuUInt uBytesCapacity {}; + + AuUInt uBytesLiveCounter {}; + AuUInt uBytesPeakCounter {}; + + bool bIsSharedWithOtherHeaps {}; +}; \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auMemoryAllocate.hpp b/Include/auROXTL/MemoryModel/auMemoryAllocate.hpp new file mode 100755 index 0000000..d0451e6 --- /dev/null +++ b/Include/auROXTL/MemoryModel/auMemoryAllocate.hpp @@ -0,0 +1,150 @@ +#pragma once + +#if defined(AURORA_ROXTL_HAS_RUNTIME) && AURORA_ROXTL_HAS_RUNTIME +namespace Aurora::Memory +{ + AuHeap *GetDefaultDiscontiguousHeap(); +} +#endif + +namespace __audetail +{ +#if defined(AURORA_ROXTL_HAS_RUNTIME) && AURORA_ROXTL_HAS_RUNTIME + inline AuHeap *gDefaultDiscontiguousHeap = Aurora::Memory::GetDefaultDiscontiguousHeap(); +#else + inline AuHeap *gDefaultDiscontiguousHeap = &gDefaultDummyHeap; +#endif +} + +template +auline AuSPtr AuMakeShared(Args &&... args) +{ + using Z = AuRemoveConst_t; + +#if !defined(AURORA_RUNTIME_HEADERS_ALWAYS_LOOKUP_HEAP) + + try + { + #if defined(AURORA_ROXTL_ALLOCATORS_USE_STD) + return AURORA_RUNTIME_MAKE_SHARED(AuForward(args)...); + #else + auto pNext = Aurora::Memory::__FAlloc(sizeof(T), alignof(T)); + if (!pNext) + { + return nullptr; + } + + auto pNextClass = (Z *)pNext; + new (pNextClass) Z (AuForward(args)...); + return AuSSPtr(pNextClass, Aurora::Memory::DefaultRuntimeDeleter {}, Aurora::Memory::SharedControlBlockAllocator {}); + #endif + } + catch (...) + { + return {}; + } + +#else + + return __audetail::gDefaultDiscontiguousHeap->NewClass(AuForward(args)...); + +#endif +} + +template +using AuHUPOf_t = AuUPtr; + +template +auto AuNullHeapPointer() +{ + return AuHeapNullUniquePointer(); +} + +template +auto AuNullPointer() +{ + return AuHeapNullUniquePointer(); +} + +template +AuHUPOf_t AuNewClassArrayUnique(AuUInt uElements, Args &&... fillCtr) +{ + return __audetail::gDefaultDiscontiguousHeap->NewClassArrayUnique(uElements, AuForward(fillCtr)...); +} + +template +AuSPtr AuNewClassArray(AuUInt uElements, Args &&... fillCtr) +{ + return __audetail::gDefaultDiscontiguousHeap->NewClassArray(uElements, AuForward(fillCtr)...); +} + +template +AuHUPOf_t AuNewClassUnique(Args &&...args) +{ + return __audetail::gDefaultDiscontiguousHeap->NewClassUnique(AuForward(args)...); +} + +template +AuSPtr AuNewClass(Args &&...args) +{ +#if !defined(AURORA_RUNTIME_HEADERS_ALWAYS_LOOKUP_HEAP) + return AuMakeShared(AuForward(args)...); +#else + return __audetail::gDefaultDiscontiguousHeap->NewClass(AuForward(args)...); +#endif +} + +template +AuHUPOf_t AuNewClassArrayUnique(AuHeap *pHeap, AuUInt uElements, Args &&... fillCtr) +{ + return pHeap->NewClassArrayUnique(uElements, AuForward(fillCtr)...); +} + +template +AuSPtr AuNewClassArray(AuHeap *pHeap, AuUInt uElements, Args &&... fillCtr) +{ + return pHeap->NewClassArray(uElements, AuForward(fillCtr)...); +} + +template +AuHUPOf_t AuNewClassUnique(AuHeap *pHeap, Args &&...args) +{ + return pHeap->NewClassUnique(AuForward(args)...); +} + +template +AuSPtr AuNewClass(AuHeap *pHeap, Args &&...args) +{ + return pHeap->NewClass(AuForward(args)...); +} + +template +AuHUPOf_t AuNewClassArrayUnique(const AuSPtr &pHeap, AuUInt uElements, Args &&... fillCtr) +{ + return pHeap->NewClassArrayUnique(uElements, AuForward(fillCtr)...); +} + +template +AuSPtr AuNewClassArray(const AuSPtr &pHeap, AuUInt uElements, Args &&... fillCtr) +{ + return pHeap->NewClassArray(uElements, AuForward(fillCtr)...); +} + +template +AuHUPOf_t AuNewClassUnique(const AuSPtr &pHeap, Args &&...args) +{ + return pHeap->NewClassUnique(AuForward(args)...); +} + +template +AuSPtr AuNewClass(const AuSPtr &pHeap, Args &&...args) +{ + return pHeap->NewClass(AuForward(args)...); +} + +template +AuHUPOf_t AuCastPointer(AuHUPOf_t &&pInPointer) +{ + // TODO: we can do better with this memory model update + return AuHeapCastPointer(AuMove(pInPointer)); +} \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auMemoryView.hpp b/Include/auROXTL/MemoryModel/auMemoryView.hpp new file mode 100755 index 0000000..4d496fb --- /dev/null +++ b/Include/auROXTL/MemoryModel/auMemoryView.hpp @@ -0,0 +1,314 @@ +/*** + Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auAuMemoryView.hpp + File: AuMemoryView.hpp + Date: 2021-9-14 + Author: Reece + Notes: Moved from Runtime +***/ +#pragma once + +struct AuMemoryViewControlBlock +{ + // Free-after-use mitigator: ensures a non-zero flag is kept whilst other memory views are present + // This helps mitigate: + // -> Take view from object + // -> Make view shared + // -> Pass off shared view to another subsystem + // -> Use the aforementioned object to resize, release, or do something bad with the memory pointed to by the initial view + // Mitgation: SysAssert(!pObject->uInUse) + AuAUInt32 *pInUseCounter {}; + + // Mitigation (cont) and reducing code reuse: + // -> Allow for [shared!] memory views to have a shared freestanding owner + // -> Ensure reference counters or other forms of memory management don't free the owner before us + // (Consider inverse construction order, for instance, we'd have to always call AuMemoryView::ResetControlBlock() + // in a derived subclass, in order release the pInUseCounter reference before the derived shared members get released) + AuSSPtr pPinner; // WARNING: as usual, std types don't validate their allocator, and our shared ptrs can be different between binaries! + + void *pCallbackHandle {}; + + // Called on zero condition (pInUseCounter == 0), or when the view is destroyed or moved (if no pInUseCounter). + void (*pfCallbackOnZero)(void *) {}; + + inline ~AuMemoryViewControlBlock(); + inline void Release(); +}; + +// A memory view that can be reinterpret cast to any type. May contain shared pointer control blocks for persistency. +template +struct AuMemoryView +{ + using U8_t = AuConditional_t; + using Void_t = AuConditional_t; + + constexpr AuMemoryView(); + + template::value)> + constexpr AuMemoryView(T &list) + { + this->ptr = list.data(); + this->length = list.size() * sizeof(typename T::value_type); + } + + constexpr AuMemoryView(const AuROString &str); + + constexpr AuMemoryView(const AuRONString &str); + + constexpr AuMemoryView(const AuString &str); + + AuMemoryView(const AuMemoryView &view); + + AuMemoryView(const AuMemoryView &view, + const AuSPtr &pThat, + void *pCallbackHandle = nullptr, + void (*pfCallbackOnZero)(void *) = nullptr); + + constexpr AuMemoryView(AuMemoryView &&view); + + template + constexpr AuMemoryView(T(&a)[Z]); + + template + constexpr AuMemoryView(AuArray &view); + + template + constexpr AuMemoryView(T *start, T *end); + + template + constexpr AuMemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, void *pCallbackHandle = nullptr, void (*pfCallbackOnZero)(void *) = nullptr); + + template + constexpr AuMemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, const AuSPtr &pRAIIOwner, void *pCallbackHandle = nullptr, void (*pfCallbackOnZero)(void *) = nullptr); + + template + constexpr AuMemoryView(T *start, AuUInt length); // WARNING: length != count + // where T = whogivesafuck + + template + constexpr AuMemoryView(T *start, AuUInt length, AuAUInt32 *pInUseCounter, void *pCallbackHandle = nullptr, void (*pfCallbackOnZero)(void *) = nullptr); // WARNING: length != count + + template + constexpr AuMemoryView(T *start, AuUInt length, AuAUInt32 *pInUseCounter, const AuSPtr &pRAIIOwner, void *pCallbackHandle = nullptr, void (*pfCallbackOnZero)(void *) = nullptr); // WARNING: length != count + +private: + template + AuMemoryView(T *start, AuUInt length, const AuMemoryViewControlBlock ©Block); + +public: + + AuMemoryView &operator =(AuMemoryView &&view); + AuMemoryView &operator =(const AuMemoryView &view); + + constexpr AuUInt ToPointerValue() const; + + constexpr AuUInt ToLength() const; + constexpr AuUInt Length() const; + + constexpr AuUInt ToSize() const; + constexpr AuUInt Size() const; + constexpr AuUInt size() const; + + template + constexpr AuUInt ToCount() const; + template + constexpr AuUInt Count() const; + + template + AuConditional_t Begin() const; + + template + AuConditional_t End() const; + + constexpr bool HasMemory() const; + + constexpr operator bool() const; + + constexpr U8_t ToPointer() const; + + constexpr U8_t begin() const; + constexpr U8_t end() const; + constexpr U8_t Begin() const; + constexpr U8_t End() const; + + AuMemoryView AtOffset(AuUInt uOffset) const; + AuMemoryView Take(AuUInt uLength) const; + + AuMemoryView Clone() const; + AuMemoryView Clone(AuHeap *pHeap, AuUInt32 uAlignment = alignof(double)) const; + + bool TryCloneSelf(bool bResetOnFailure = true); + + AuUInt CopyInto(const AuMemoryView &write) const; + + template + AuUInt CopyFrom(const AuMemoryView &read) const + { + auto uLength = AuMin(this->uLength, read.uLength); + AuMemcpy(this->pBase, read.pBase, uLength); + return uLength; + } + + bool HasControlBlock() const; + + /// Creates a shader pointer of the view with an optional parent + AuSPtr TryPromoteToSharedView(AuSPtr pParent = {}) const; + + /// Creates a shader pointer of the view with an optional parent + /// If *this already contains a shared parent, will return nullptr + AuSPtr TryPromoteToSharedViewNoParentNesting(AuSPtr pParent = {}) const; + + /// Shares ownership of pCopy, returning false if there is no shared parent. + bool TryDemoteFromSharedView(const AuSPtr &pCopy); + + /// Shares ownership of pCopy, returning false if there is no shared parent. + bool TryDemoteFromReference(const AuMemoryView &refCopy); + + /// Copies the memory view of a shared memory view. + /// If the memory view has a shared parent, the memory view and its parent shared pointer is copied into *this. + /// If the memory view does not have a shared parent, the memory view and its control block is copied into *this. + void DemoteFromSharedView(const AuSPtr &pCopy); + + /// Interop for other APIs that allow for pinning shared pointers (std::shared_ptr) + AuSPtr ToSharedControlBlock(bool *pbFailed = nullptr); + + union + { + Void_t /*const*/ ptr; + Void_t /*const*/ pBase; + U8_t ptrU8; + AuUInt uPtr; + }; + union + { + AuUInt /*const*/ length; + AuUInt /*const*/ uLength; + }; + +private: + AuMemoryViewControlBlock controlBlock; +}; + +using AuMemoryViewRead = AuMemoryView; +using AuMemoryViewWrite = AuMemoryView; + +// A memory view with an output variable reference for bytes consumed/provided scenarios. +// ( they happen enough to justify this class for binding engines. ) +// ( this is also easier to bind than arbitrary POD pointers of no assertable lifespan by typical style expectations. ) +template +struct AuMemoryViewStream : AuMemoryView +{ + template::value)> + constexpr AuMemoryViewStream(T &list, AuUInt &length) : AuMemoryView(list), outVariable(length) + { + outVariable = 0; + } + + constexpr AuMemoryViewStream(const AuString &str, AuUInt &length) : AuMemoryView(str), outVariable(length) + { + outVariable = 0; + } + + template + constexpr AuMemoryViewStream(T *start, T *end, AuUInt &length) : AuMemoryView(start, end), outVariable(length) + { + outVariable = 0; + } + + template + constexpr AuMemoryViewStream(T *start, AuUInt &length) : AuMemoryView(start, length), outVariable(length) + { + outVariable = 0; + } + + template + constexpr AuMemoryViewStream(AuArray &view, + AuUInt &length) : + AuMemoryView(view), + outVariable(length) + { + outVariable = 0; + } + + template::value>::type* = nullptr> + constexpr AuMemoryViewStream(T &list) : AuMemoryView(list), outVariable(unused) + { + outVariable = 0; + } + + constexpr AuMemoryViewStream(const AuString &str) : + AuMemoryView(str), + outVariable(unused) + { + outVariable = 0; + } + + constexpr AuMemoryViewStream(const AuROString &str) : + AuMemoryView(str), + outVariable(unused) + { + outVariable = 0; + } + + constexpr AuMemoryViewStream(const AuRONString &str) : + AuMemoryView(str), + outVariable(unused) + { + outVariable = 0; + } + + template + constexpr AuMemoryViewStream(T *start, T *end) : AuMemoryView(start, end), outVariable(unused) + { + outVariable = 0; + } + + constexpr AuMemoryViewStream(AuMemoryView in) : AuMemoryView(in.ptr, in.length), outVariable(unused) + { + outVariable = 0; + } + + constexpr AuMemoryViewStream(AuMemoryView in, AuUInt &len) : AuMemoryView(in.ptr, in.length), outVariable(len) + { + outVariable = 0; + } + + template + constexpr AuMemoryViewStream(T(&a)[Z]) : AuMemoryView(a), outVariable(unused) + { + outVariable = 0; + } + + constexpr bool HasMemory() const + { + return this->ptr && this->length; + } + + constexpr operator bool() const + { + return HasMemory(); + } + + void CopyStreamInto(const AuMemoryView &write) const + { + auto uLength = AuMin(this->uLength, write.uLength); + AuMemcpy(write.pBase, this->pBase, uLength); + this->outVariable = uLength; + } + + template + void CopyStreamFrom(const AuMemoryView &read) const + { + auto uLength = AuMin(this->uLength, read.uLength); + AuMemcpy(this->pBase, read.pBase, uLength); + this->outVariable = uLength; + } + + AuUInt &outVariable; +private: + AuUInt unused; +}; + +using AuMemoryViewStreamRead = AuMemoryViewStream; +using AuMemoryViewStreamWrite = AuMemoryViewStream; \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auMemoryView.ipp b/Include/auROXTL/MemoryModel/auMemoryView.ipp new file mode 100755 index 0000000..3baff4e --- /dev/null +++ b/Include/auROXTL/MemoryModel/auMemoryView.ipp @@ -0,0 +1,624 @@ +/*** + Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auAuMemoryView.ipp + File: AuMemoryView.hpp + Date: 2021-9-14 + Author: Reece + Notes: Moved from Runtime +***/ +#pragma once + +AuMemoryViewControlBlock::~AuMemoryViewControlBlock() +{ + this->Release(); +} + +void AuMemoryViewControlBlock::Release() +{ + if (auto pCounter = AuExchange(this->pInUseCounter, nullptr)) + { + if (AuAtomicSub(pCounter, 1u) == 0) + { + if (this->pfCallbackOnZero) + { + this->pfCallbackOnZero(this->pCallbackHandle); + } + } + } + else + { + if (this->pfCallbackOnZero) + { + this->pfCallbackOnZero(this->pCallbackHandle); + } + } + + AuResetMember(this->pPinner); + AuResetMember(this->pfCallbackOnZero); +} + +template +constexpr AuMemoryView::AuMemoryView() +{ + this->ptr = nullptr; + this->length = 0; +} + +template +constexpr AuMemoryView::AuMemoryView(const AuROString &str) +{ + static_assert(Readonly_b, "ReadOnly string view must not be placed in a writable memory view"); + this->ptr = str.data(); + this->length = str.size(); +} + +template +constexpr AuMemoryView::AuMemoryView(const AuRONString &str) +{ + static_assert(Readonly_b, "ReadOnly string view must not be placed in a writable memory view"); + this->ptr = str.data(); + this->length = str.size(); +} + +template +constexpr AuMemoryView::AuMemoryView(const AuString &str) +{ + this->ptr = str.data(); + this->length = str.size(); +} + +template +AuMemoryView::AuMemoryView(const AuMemoryView &view) +{ + this->ptr = view.ptr; + this->length = view.length; + this->controlBlock = view.controlBlock; + if (this->controlBlock.pInUseCounter) + { + AuAtomicAdd(this->controlBlock.pInUseCounter, 1u); + } +} + +template +AuMemoryView::AuMemoryView(const AuMemoryView &view, + const AuSPtr &pThat, + void *pCallbackHandle, + void (*pfCallbackOnZero)(void *)) +{ + this->ptr = view.ptr; + this->length = view.length; + this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter; + if (this->controlBlock.pInUseCounter) + { + AuAtomicAdd(this->controlBlock.pInUseCounter, 1u); + } + if (pThat) + { + if (view.controlBlock.pPinner) + { + auto pThat2 = AuMakeSharedArray>(2); + this->controlBlock.pPinner = pThat2; + if (!this->controlBlock.pPinner) + { + AuMemoryPanic("OOM"); + } + pThat2.get()[0] = pThat; + pThat2.get()[1] = view.controlBlock.pPinner; + } + else + { + this->controlBlock.pPinner = pThat; + } + } + else + { + this->controlBlock.pPinner = view.controlBlock.pPinner; + } + if (pfCallbackOnZero) + { + this->controlBlock.pCallbackHandle = pCallbackHandle; + this->controlBlock.pfCallbackOnZero = pfCallbackOnZero; + } +} + +template +constexpr AuMemoryView::AuMemoryView(AuMemoryView &&view) +{ + this->ptr = view.ptr; + this->length = view.length; + this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter; + this->controlBlock.pPinner = AuMove(view.controlBlock.pPinner); + this->controlBlock.pfCallbackOnZero = view.controlBlock.pfCallbackOnZero; + this->controlBlock.pCallbackHandle = view.controlBlock.pCallbackHandle; + view.controlBlock.pInUseCounter = nullptr; + view.controlBlock.pfCallbackOnZero = nullptr; +} + +template +template +constexpr AuMemoryView::AuMemoryView(T(&a)[Z]) +{ + this->ptr = &a[0]; + this->length = Z * sizeof(T); +} + +template +template +constexpr AuMemoryView::AuMemoryView(AuArray &view) +{ + this->ptr = view.begin(); + this->length = Z * sizeof(T); +} + +template +template +constexpr AuMemoryView::AuMemoryView(T *start, T *end) +{ + this->ptr = start; + if constexpr (AuIsSame_v) + { + this->length = reinterpret_cast(end) - reinterpret_cast(start); + } + else + { + this->length = (end - start) * sizeof(T); + } +} + +template +template +constexpr AuMemoryView::AuMemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, void *pCallbackHandle, void (*pfCallbackOnZero)(void *)) +{ + this->ptr = start; + if constexpr (AuIsSame_v) + { + this->length = reinterpret_cast(end) - reinterpret_cast(start); + } + else + { + this->length = (end - start) * sizeof(T); + } + + this->controlBlock.pInUseCounter = pInUseCounter; + AuAtomicAdd(pInUseCounter, 1u); + this->controlBlock.pCallbackHandle = pCallbackHandle; + this->controlBlock.pfCallbackOnZero = pfCallbackOnZero; +} + +template +template +constexpr AuMemoryView::AuMemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, const AuSPtr &pRAIIOwner, void *pCallbackHandle, void (*pfCallbackOnZero)(void *)) +{ + this->ptr = start; + if constexpr (AuIsSame_v) + { + this->length = reinterpret_cast(end) - reinterpret_cast(start); + } + else + { + this->length = (end - start) * sizeof(T); + } + + this->controlBlock.pInUseCounter = pInUseCounter; + AuAtomicAdd(pInUseCounter, 1u); + this->controlBlock.pPinner = pRAIIOwner; + this->controlBlock.pCallbackHandle = pCallbackHandle; + this->controlBlock.pfCallbackOnZero = pfCallbackOnZero; +} + +template +template +constexpr AuMemoryView::AuMemoryView(T *start, AuUInt length) // WARNING: length != count + // where T = whogivesafuck +{ + this->ptr = start; + this->length = length; +} + +template +template +constexpr AuMemoryView::AuMemoryView(T *start, AuUInt length, AuAUInt32 *pInUseCounter, void *pCallbackHandle, void (*pfCallbackOnZero)(void *)) // WARNING: length != count +{ + this->ptr = start; + this->length = length; + this->controlBlock.pInUseCounter = pInUseCounter; + AuAtomicAdd(pInUseCounter, 1u); + this->controlBlock.pCallbackHandle = pCallbackHandle; + this->controlBlock.pfCallbackOnZero = pfCallbackOnZero; +} + +template +template +constexpr AuMemoryView::AuMemoryView(T *start, AuUInt length, AuAUInt32 *pInUseCounter, const AuSPtr &pRAIIOwner, void *pCallbackHandle, void (*pfCallbackOnZero)(void *)) // WARNING: length != count +{ + this->ptr = start; + this->length = length; + this->controlBlock.pInUseCounter = pInUseCounter; + AuAtomicAdd(pInUseCounter, 1u); + this->controlBlock.pPinner = pRAIIOwner; + this->controlBlock.pCallbackHandle = pCallbackHandle; + this->controlBlock.pfCallbackOnZero = pfCallbackOnZero; +} + +template +template +AuMemoryView::AuMemoryView(T *start, AuUInt length, const AuMemoryViewControlBlock ©Block) +{ + this->ptr = start; + this->length = length; + this->controlBlock = copyBlock; + if (this->controlBlock.pInUseCounter) + { + AuAtomicAdd(this->controlBlock.pInUseCounter, 1u); + } +} + +template +AuMemoryView &AuMemoryView::operator =(AuMemoryView &&view) +{ + this->ptr = view.ptr; + this->length = view.length; + this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter; + view.controlBlock.pInUseCounter = nullptr; + this->controlBlock.pPinner = AuMove(view.controlBlock.pPinner); + this->controlBlock.pfCallbackOnZero = view.controlBlock.pfCallbackOnZero; + this->controlBlock.pCallbackHandle = view.controlBlock.pCallbackHandle; + view.controlBlock.pfCallbackOnZero = nullptr; + return *this; +} + +template +AuMemoryView &AuMemoryView::operator =(const AuMemoryView &view) +{ + this->ptr = view.ptr; + this->length = view.length; + this->controlBlock.pInUseCounter = view.controlBlock.pInUseCounter; + if (this->controlBlock.pInUseCounter) + { + AuAtomicAdd(this->controlBlock.pInUseCounter, 1u); + } + this->controlBlock.pPinner = view.controlBlock.pPinner; + this->controlBlock.pfCallbackOnZero = view.controlBlock.pfCallbackOnZero; + this->controlBlock.pCallbackHandle = view.controlBlock.pCallbackHandle; + return *this; +} + +template +constexpr AuUInt AuMemoryView::ToPointerValue() const +{ + return this->uPtr; +} + +template +constexpr AuUInt AuMemoryView::ToLength() const +{ + return this->length; +} + +template +constexpr AuUInt AuMemoryView::Length() const +{ + return this->length; +} + +template +constexpr AuUInt AuMemoryView::ToSize() const +{ + return this->length; +} + +template +constexpr AuUInt AuMemoryView::Size() const +{ + return this->length; +} + +template +template +constexpr AuUInt AuMemoryView::ToCount() const +{ + return this->length / sizeof(T); +} + +template +template +constexpr AuUInt AuMemoryView::Count() const +{ + return this->length / sizeof(T); +} + +template +template +AuConditional_t AuMemoryView::Begin() const +{ + return reinterpret_cast>(ptr); +} + +template +template +AuConditional_t AuMemoryView::End() const +{ + return Begin() + ToCount(); +} + +template +constexpr bool AuMemoryView::HasMemory() const +{ + return this->ptr && this->length; +} + +template +constexpr AuMemoryView::operator bool() const +{ + return this->HasMemory(); +} + +template +constexpr AuMemoryView::U8_t AuMemoryView::ToPointer() const +{ + return this->ptrU8; +} + +template +constexpr AuMemoryView::U8_t AuMemoryView::begin() const +{ + return this->ptrU8; +} + +template +constexpr AuMemoryView::U8_t AuMemoryView::end() const +{ + return this->ptrU8 + this->length; +} + +template +constexpr AuMemoryView::U8_t AuMemoryView::Begin() const +{ + return this->ptrU8; +} + +template +constexpr AuMemoryView::U8_t AuMemoryView::End() const +{ + return this->ptrU8 + this->length; +} + +template +constexpr AuUInt AuMemoryView::size() const +{ + return this->length; +} + +template +AuMemoryView AuMemoryView::AtOffset(AuUInt uOffset) const +{ + if (uOffset < this->uLength) + { + return AuMemoryView((AuUInt8 *)this->pBase + uOffset, + this->uLength - uOffset, + this->controlBlock); + } + else + { + return {}; + } +} + +template +AuMemoryView AuMemoryView::Take(AuUInt uLength) const +{ + if (uLength <= this->uLength) + { + return AuMemoryView((AuUInt8 *)this->pBase, + uLength, + this->controlBlock); + } + else + { + return {}; + } +} + +template +AuMemoryView AuMemoryView::Clone() const +{ + auto uLength = this->uLength; + auto pData = AuMakeSharedArray(uLength); + if (!pData) + { + return {}; + } + + AuMemcpy(pData.get(), this->pBase, uLength); + return AuMemoryView(AuMemoryView(pData.get(), uLength), pData); +} + +template +AuMemoryView AuMemoryView::Clone(AuHeap *pHeap, AuUInt32 uAlignment) const +{ + auto uLength = this->uLength; + auto pData = __audetail::AllocateArray(pHeap, uLength, uAlignment); + if (!pData) + { + return {}; + } + + AuMemcpy(pData.get(), this->pBase, uLength); + return AuMemoryView(AuMemoryView(pData.get(), uLength), pData); +} + +template +bool AuMemoryView::TryCloneSelf(bool bResetOnFailure) +{ + auto replacement = Clone(); + if (!replacement) + { + if (bResetOnFailure) + { + AuResetMember(*this); + } + return false; + } + AuResetMember(*this, replacement); + return true; +} + +template +bool AuMemoryView::HasControlBlock() const +{ + return this->controlBlock.pInUseCounter || + this->controlBlock.pPinner || + this->controlBlock.pfCallbackOnZero; +} + +template +AuSPtr> AuMemoryView::TryPromoteToSharedView(AuSPtr pParent) const +{ +#if 0 + bool bHasControlBlock = this->HasControlBlock(); + + if (bHasControlBlock) + { + if (pParent) + { + return AuMakeShared(*this, pParent); + } + else + { + return AuMakeShared(*this); + } + } + else + { + if (pParent) + { + return AuMakeShared(*this, pParent); + } + else + { + return {}; + } + } +#else + if (pParent) + { + return AuMakeShared(*this, pParent); + } + + if (this->HasControlBlock()) + { + return AuMakeShared(*this); + } + + return {}; +#endif +} + +template +AuSPtr> AuMemoryView::TryPromoteToSharedViewNoParentNesting(AuSPtr pParent) const +{ + if (this->HasControlBlock()) + { + return AuMakeShared(*this); + } + + if (pParent) + { + return AuMakeShared(*this, pParent); + } + + return {}; +} + +template +bool AuMemoryView::TryDemoteFromSharedView(const AuSPtr> &pCopy) +{ + if (pCopy && pCopy->HasControlBlock()) + { + AuResetMember(*this, AuConstReference(*pCopy.get())); + return true; + } + else + { + return false; + } +} + +template +bool AuMemoryView::TryDemoteFromReference(const AuMemoryView &refCopy) +{ + if (refCopy.HasControlBlock()) + { + AuResetMember(*this, refCopy); + return true; + } + else + { + return false; + } +} + +template +void AuMemoryView::DemoteFromSharedView(const AuSPtr> &pCopy) +{ + if (!pCopy) + { + AuResetMember(*this); + return; + } + + if (pCopy->HasControlBlock()) + { + AuResetMember(*this, AuConstReference(*pCopy.get())); + } + else + { + AuResetMember(*this, AuConstReference(*pCopy.get()), pCopy); + } +} + +template +AuSPtr AuMemoryView::ToSharedControlBlock(bool *pbFailed) +{ + 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; + pShared->pfCallbackOnZero = this->controlBlock.pfCallbackOnZero; + pShared->pCallbackHandle = this->controlBlock.pCallbackHandle; + return pShared; + } + + if (this->controlBlock.pPinner) + { + return this->controlBlock.pPinner; + } + + return {}; +} + +template +AuUInt AuMemoryView::CopyInto(const AuMemoryView &write) const +{ + auto uLength = AuMin(this->uLength, write.uLength); + AuMemcpy(write.pBase, this->pBase, uLength); + return uLength; +} + diff --git a/Include/auROXTL/MemoryModel/auPMRAllocator.hpp b/Include/auROXTL/MemoryModel/auPMRAllocator.hpp new file mode 100755 index 0000000..f1f3136 --- /dev/null +++ b/Include/auROXTL/MemoryModel/auPMRAllocator.hpp @@ -0,0 +1,263 @@ +/*** + Copyright (C) 2023-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auPMRAllocator.hpp + Date: 2023-12-22 + Author: Reece + Note: Moved from Runtime +***/ +#pragma once + +template +struct AuPMRAllocator +{ + using value_type = T; + + using size_type = size_t; + using difference_type = ptrdiff_t; + + using propagate_on_container_move_assignment = AuTrueType; + using propagate_on_container_copy_assignment = AuTrueType; + using is_always_equal = AuFalseType; + +#if defined(AU_LANG_CPP_17) + using pointer = T *; + using const_pointer = const T *; + + using reference = T &; + using const_reference = const T &; + + template + struct rebind + { + using other = AuPMRAllocator; + }; + + T *address(T &val) const noexcept + { + return std::addressof(val); + } + + const T *address(const T &val) const noexcept + { + return std::addressof(val); + } +#endif + + inline AuPMRAllocator(AuSSPtr pHeap) : + #if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + spHeap(pHeap), + pHeap(pHeap.get()) + #else + spHeap(pHeap) + #endif + { } + + inline AuPMRAllocator(AuHeap *pHeap, AuSSPtr pThat = {}) : + #if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + spHeap(pThat), + pHeap(pHeap) + #else + spHeap(AuSharedPointerFromShared(pHeap, pThat)) + #endif + { } + + template + inline AuPMRAllocator(const AuPMRAllocator &that) : + spHeap(that.spHeap) + #if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + ,pHeap(that.pHeap) + #endif + { } + + inline AuPMRAllocator(const AuPMRAllocator &that) : + spHeap(that.spHeap) + #if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + ,pHeap(that.pHeap) + #endif + { } + + inline AuPMRAllocator(AuPMRAllocator &&that) : + spHeap(that.spHeap) + #if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + ,pHeap(that.pHeap) + #endif + { } + + + AU_DEF(AuPMRAllocator) + AU_OPERATOR_COPY_MOVE(AuPMRAllocator) + + void *allocate_bytes(std::size_t nbytes, + std::size_t alignment = alignof(std::max_align_t)) + { + if (auto pRet = this->GetHeapRaw()->FAlloc(nbytes, alignment)) + { + return pRet; + } + else + { + throw std::bad_alloc(); + } + } + + void deallocate_bytes(void *p, + std::size_t nbytes, + std::size_t alignment = alignof(std::max_align_t)) noexcept + { + return this->GetHeapRaw()->Free(p); + } + +#if defined(AU_LANG_CPP_23_) + std::allocation_result allocate_at_least(const size_t count) + { + auto pThat = this->allocate(count); + return { (T *)pThat, this->GetHeapRaw()->GetChunkSize(pThat) / sizeof(T) }; + } +#endif + + template + void construct(U *p, Args&&... args) + { + new ((void *)p) U(AuForward(args)...); + } + + template + void construct_at(U *p, Args&&... args) + { + new ((void *)p) U(AuForward(args)...); + } + + void deallocate(const T *pType, + const size_t count) noexcept + { + this->deallocate_bytes((void *)pType, 0, 0); + } + + AU_ALLOC T *allocate(const size_t count) + { + if (!count) + { + return nullptr; + } + + return (T *)this->allocate_bytes(count * sizeof(T), alignof(T)); + } + + template + U *allocate_object(std::size_t n = 1) + { + return (U *)this->allocate_bytes(sizeof(U) * n, alignof(U)); + } + + template + void deallocate_object(U *p, std::size_t n = 1) + { + this->deallocate_bytes(p, 0, 0); + } + + template + U *new_object(CtorArgs&&... args) + { + U *p = this->allocate_object(); + try + { + this->construct(p, AuForward(args)...); + } + catch (...) + { + this->deallocate_object(p); + throw; + } + return p; + } + + template + void delete_object(U *p) + { + if constexpr (AuIsClass_v && + !AuIsTriviallyDestructible_v) + { + p->~U(); + } + + this->deallocate_object(p); + } + + bool IsInitialized() const + { + #if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + return bool(this->pHeap); + #else + return bool(this->spHeap); + #endif + } + + AuSSPtr GetHeap() const + { + #if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + return AuSharedPointerFromShared(this->pHeap, this->spHeap); + #else + return this->spHeap; + #endif + } + + AuHeap *GetHeapRaw() const + { + AuHeap *pRet {}; + + #if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + pRet = this->pHeap; + #else + pRet = this->spHeap.get(); + #endif + + if (pRet) + { + return pRet; + } + + #if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + return this->pHeap = __audetail::gDefaultDiscontiguousHeap; + #else + return (this->spHeap = AuUnsafeRaiiToShared(__audetail::gDefaultDiscontiguousHeap)).get(); + #endif + } + + template + bool operator==(const AuPMRAllocator &rhs) noexcept + { + return this->GetHeapRaw() == rhs.GetHeapRaw(); + } + + template + bool operator!=(const AuPMRAllocator &rhs) noexcept + { + return this->GetHeapRaw() == rhs.GetHeapRaw(); + } + +private: +#if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER) + mutable AuSSPtr spHeap; + mutable AuHeap *pHeap {}; +#else + mutable AuSSPtr spHeap; +#endif + + template + friend struct AuPMRAllocator; +}; + +template +inline bool operator==(const AuPMRAllocator &lhs, + const AuPMRAllocator &rhs) noexcept +{ + return lhs.GetHeapRaw() == rhs.GetHeapRaw(); +} + +template +inline bool operator!=(const AuPMRAllocator &lhs, + const AuPMRAllocator &rhs) noexcept +{ + return lhs.GetHeapRaw() != rhs.GetHeapRaw(); +} \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auSetAllocator.hpp b/Include/auROXTL/MemoryModel/auSetAllocator.hpp index 4a277e3..fc76c6d 100644 --- a/Include/auROXTL/MemoryModel/auSetAllocator.hpp +++ b/Include/auROXTL/MemoryModel/auSetAllocator.hpp @@ -7,14 +7,8 @@ ***/ #pragma once -namespace Aurora::Memory -{ - struct Heap; -} +template +bool AuSetAllocator(T &that, AuHeap *pHeap); template -static bool AuSetAllocator(T &that, Aurora::Memory::Heap *pHeap); - -template -static bool AuSetAllocator(T &that, const AuSPtr &pHeap); - +bool AuSetAllocator(T &that, const AuSPtr &pHeap); \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auSetAllocator.ipp b/Include/auROXTL/MemoryModel/auSetAllocator.ipp index f16bab3..7f0a25a 100644 --- a/Include/auROXTL/MemoryModel/auSetAllocator.ipp +++ b/Include/auROXTL/MemoryModel/auSetAllocator.ipp @@ -12,7 +12,7 @@ namespace __audetail template struct AuHasSetAllocatorRawVoid { - template static constexpr AuTrueType Test(decltype(static_cast(&C::SetAllocator))); + template static constexpr AuTrueType Test(decltype(static_cast(&C::SetAllocator))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; @@ -20,14 +20,14 @@ namespace __audetail template struct AuHasSetAllocatorRawBool { - template static constexpr AuTrueType Test(decltype(static_cast(&C::SetAllocator))); + template static constexpr AuTrueType Test(decltype(static_cast(&C::SetAllocator))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; template struct AuHasSetHeapRawVoid { - template static constexpr AuTrueType Test(decltype(static_cast(&C::SetHeap))); + template static constexpr AuTrueType Test(decltype(static_cast(&C::SetHeap))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; @@ -35,15 +35,15 @@ namespace __audetail template struct AuHasSetHeapRawBool { - template static constexpr AuTrueType Test(decltype(static_cast(&C::SetHeap))); + template static constexpr AuTrueType Test(decltype(static_cast(&C::SetHeap))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; template struct AuHasSetAllocatorSVoid { - template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetAllocator))); - template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetAllocator))); + template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetAllocator))); + template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetAllocator))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; @@ -51,8 +51,8 @@ namespace __audetail template struct AuHasSetAllocatorSBool { - template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetAllocator))); - template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetAllocator))); + template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetAllocator))); + template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetAllocator))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; @@ -60,8 +60,8 @@ namespace __audetail template struct AuHasSetHeapSVoid { - template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetHeap))); - template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetHeap))); + template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetHeap))); + template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetHeap))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; @@ -69,8 +69,8 @@ namespace __audetail template struct AuHasSetHeapSBool { - template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetHeap))); - template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetHeap))); + template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetHeap))); + template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetHeap))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; @@ -78,8 +78,8 @@ namespace __audetail template struct AuHasSetHeapSharedSVoid { - template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetHeapShared))); - template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetHeapShared))); + template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetHeapShared))); + template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetHeapShared))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; @@ -87,8 +87,8 @@ namespace __audetail template struct AuHasSetHeapSharedSBool { - template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetHeapShared))); - template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetHeapShared))); + template static constexpr AuTrueType Test(decltype(static_cast)>(&C::SetHeapShared))); + template static constexpr AuTrueType Test(decltype(static_cast &)>(&C::SetHeapShared))); template static constexpr AuFalseType Test(...); using type = decltype(Test(0)); }; @@ -136,7 +136,7 @@ namespace __audetail } template -static bool AuSetAllocator(T &that, Aurora::Memory::Heap *pHeap) +bool AuSetAllocator(T &that, AuHeap *pHeap) { if (!pHeap) { @@ -335,7 +335,7 @@ static bool AuSetAllocator(T &that, Aurora::Memory::Heap *pHeap) template -static bool AuSetAllocator(T &that, const AuSPtr &pHeap) +bool AuSetAllocator(T &that, const AuSPtr &pHeap) { if (!pHeap) { diff --git a/Include/auROXTL/MemoryModel/auUniquePointer.hpp b/Include/auROXTL/MemoryModel/auUniquePointer.hpp new file mode 100755 index 0000000..f027eaa --- /dev/null +++ b/Include/auROXTL/MemoryModel/auUniquePointer.hpp @@ -0,0 +1,71 @@ +/*** + Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auUniquePointer.hpp + Date: 2024-09-13 + Author: Reece +***/ +#pragma once + +template +struct AuUniquePointer +{ + AuUniquePointer(); + AuUniquePointer(std::nullptr_t); + explicit AuUniquePointer(T *pThat); + explicit AuUniquePointer(T *pThat, const Deleter_t &deleter); + explicit AuUniquePointer(T *pThat, Deleter_t &&deleter); + + AuUniquePointer(AuUniquePointer &&that) noexcept; + + template + AuUniquePointer(AuUniquePointer &&that); + + ~AuUniquePointer(); + + AuUniquePointer &operator=(std::nullptr_t); + + template + AuUniquePointer &operator=(AuUniquePointer &&that) noexcept; + AuUniquePointer &operator=(AuUniquePointer &&that) noexcept; + + AuUniquePointer(AuUniquePointer const&) = delete; + AuUniquePointer &operator=(AuUniquePointer const&) = delete; + + T *operator->() const; + T &operator*() const; + + T *get() const; + explicit operator bool() const; + + T *Release() noexcept; + T* release() noexcept; + + void Swap(AuUniquePointer &that) noexcept; + void swap(AuUniquePointer &that) noexcept; + + void Reset(); + void reset(); + + const Deleter_t &GetDeleter() const noexcept; + const Deleter_t &get_deleter() const noexcept; + +private: + T *pThat {}; + Deleter_t deleter {}; +}; + +template +void Swap(AuUniquePointer &lhs, AuUniquePointer &rhs) +{ + lhs.swap(rhs); +} + +namespace std +{ + template + void swap(AuUniquePointer &lhs, AuUniquePointer &rhs) + { + lhs.swap(rhs); + } +} \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auUniquePointer.ipp b/Include/auROXTL/MemoryModel/auUniquePointer.ipp new file mode 100755 index 0000000..731830f --- /dev/null +++ b/Include/auROXTL/MemoryModel/auUniquePointer.ipp @@ -0,0 +1,187 @@ +/*** + Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auUniquePointer.ipp + Date: 2024-09-13 + Author: Reece +***/ +#pragma once + +template +AuUniquePointer::AuUniquePointer() +{} + +template +AuUniquePointer::AuUniquePointer(std::nullptr_t) +{} + +template +AuUniquePointer::AuUniquePointer(T *pThat) : + pThat(pThat) +{} + +template +AuUniquePointer::AuUniquePointer(T *pThat, const Deleter_t &deleter) : + pThat(pThat), + deleter(deleter) +{} + +template +AuUniquePointer::AuUniquePointer(T *pThat, Deleter_t &&deleter) : + pThat(pThat), + deleter(AuMove(deleter)) +{} + +template +AuUniquePointer::AuUniquePointer(AuUniquePointer &&that) noexcept +{ + that.Swap(*this); +} + +template +template +AuUniquePointer::AuUniquePointer(AuUniquePointer &&that) +{ + AuUniquePointer temp(that.Release(), that.GetDeleter()); + temp.Swap(*this); +} + +template +AuUniquePointer::~AuUniquePointer() +{ + if (!this->pThat) + { + return; + } + + if constexpr (AuIsFunction_v) + { + if (this->deleter) + { + this->deleter(this->pThat); + } + else + { + AuDefaultDeleter()(this->pThat); + } + } + else + { + this->deleter(this->pThat); + } +} + +template +AuUniquePointer &AuUniquePointer::operator=(std::nullptr_t) +{ + this->Reset(); + return *this; +} + +template +template +AuUniquePointer &AuUniquePointer::operator=(AuUniquePointer &&that) noexcept +{ + AuUniquePointer temp(that.Release(), that.GetDeleter()); + temp.Swap(*this); + return *this; +} + +template +AuUniquePointer &AuUniquePointer::operator=(AuUniquePointer &&that) noexcept +{ + that.Swap(*this); + return *this; +} + +template +T *AuUniquePointer::operator->() const +{ + return this->pThat; +} + +template +T &AuUniquePointer::operator*() const +{ + return *this->pThat; +} + +template +T *AuUniquePointer::get() const +{ + return this->pThat; +} + +template +AuUniquePointer::operator bool() const +{ + return this->pThat; +} + +template +T *AuUniquePointer::Release() noexcept +{ + T *pRet {}; + AuSwap(pRet, this->pThat); + return pRet; +} + +template +T *AuUniquePointer::release() noexcept +{ + return this->Release(); +} + +template +void AuUniquePointer::Swap(AuUniquePointer &that) noexcept +{ + AuSwap(this->pThat, that.pThat); + AuSwap(this->deleter, that.deleter); +} + +template +void AuUniquePointer::swap(AuUniquePointer &that) noexcept +{ + this->Swap(that); +} + +template +void AuUniquePointer::Reset() +{ + if (auto pThat = Release()) + { + if constexpr (AuIsFunction_v) + { + if (this->deleter) + { + this->deleter(pThat); + } + else + { + AuDefaultDeleter()(pThat); + } + } + else + { + this->deleter(pThat); + } + } +} + +template +void AuUniquePointer::reset() +{ + this->Reset(); +} + +template +const Deleter_t &AuUniquePointer::GetDeleter() const noexcept +{ + return this->deleter; +} + +template +const Deleter_t &AuUniquePointer::get_deleter() const noexcept +{ + return this->GetDeleter(); +} \ No newline at end of file diff --git a/Include/auROXTL/Objects/SOO.hpp b/Include/auROXTL/Objects/SOO.hpp index f5bf195..5fb6e02 100644 --- a/Include/auROXTL/Objects/SOO.hpp +++ b/Include/auROXTL/Objects/SOO.hpp @@ -172,7 +172,19 @@ using Type = Type ## SOO; AUROXTL_INTERFACE_SOO_HDR_EX2(vis, Type, extends, targetSize, (AU_NO_COPY_NO_MOVE(Type ## SOO)), ## __VA_ARGS__) #define AUROXTL_INTERFACE_SOO_HDR(Type, extends, targetSize, ...) \ - AUROXTL_INTERFACE_SOO_HDR_EX(, Type, extends, targetSize, ## __VA_ARGS__) + AUROXTL_INTERFACE_SOO_HDR_EX(, Type, extends, targetSize, ## __VA_ARGS__) \ + \ + template \ + extends ## Unique_t Type ## UniqueOnHeap(AuHeap *pHeap, T &&... args) \ + { \ + return pHeap->NewClassUnique(AuForward(args)...); \ + } \ + \ + template \ + extends ## Shared_t Type ## SharedOnHeap(AuHeap *pHeap, T &&... args) \ + { \ + return pHeap->NewClass(AuForward(args)...); \ + } #define AUROXTL_INTERFACE_SOO_SRC_EX(vis, Type, FullType, ...) \ vis Type ## SOO::Type ## SOO(AU_FOR_EACH_FIRST(_AUROXTL_INTERRFACE_SOO_EMITTER_0, _AUROXTL_INTERRFACE_SOO_EMITTER_1, ## __VA_ARGS__, (AuUInt32, uSize))) \ diff --git a/Include/auROXTL/STLShims/ExtendStlLikeSharedPtr.hpp b/Include/auROXTL/STLShims/ExtendStlLikeSharedPtr.hpp index 7d2e97e..14d6626 100644 --- a/Include/auROXTL/STLShims/ExtendStlLikeSharedPtr.hpp +++ b/Include/auROXTL/STLShims/ExtendStlLikeSharedPtr.hpp @@ -141,15 +141,33 @@ namespace Aurora::Memory #endif } - template < class Y, class Deleter > - ExSharedPtr(AURORA_RUNTIME_AU_UNIQUE_PTR &&r) : Base_t(AuMove(r)) + template + ExSharedPtr(AURORA_RUNTIME_AU_UNIQUE_PTR &&r) { + if constexpr (AuIsFunction_v) + { + if (r.get_deleter()) + { + this->~ExSharedPtr(); + new (this) ExSharedPtr(r.release(), r.get_deleter()); + } + else + { + this->~ExSharedPtr(); + new (this) ExSharedPtr(r.release()); + } + } + else + { + this->~ExSharedPtr(); + new (this) ExSharedPtr(r.release(), r.get_deleter()); + } + #if !defined(_AURORA_NULLEXPT_ENABLE_UB) _cache(); #endif } - template void swap(ExSharedPtr &in) { diff --git a/Include/auROXTL/auBST.hpp b/Include/auROXTL/auBST.hpp index 32aa7c8..2e6a5e4 100644 --- a/Include/auROXTL/auBST.hpp +++ b/Include/auROXTL/auBST.hpp @@ -17,7 +17,7 @@ template , class Allo using AuBST = AURORA_RUNTIME_AU_BST; template > -using AuBSTOfHeap = AuBST>>; +using AuBSTOfHeap = AuBST>>; template struct AuIsBST : AuFalseType diff --git a/Include/auROXTL/auHashMap.hpp b/Include/auROXTL/auHashMap.hpp index 9958bd0..24c24fd 100644 --- a/Include/auROXTL/auHashMap.hpp +++ b/Include/auROXTL/auHashMap.hpp @@ -17,7 +17,7 @@ template , class Equal_t = AuHa using AuHashMap = AURORA_RUNTIME_AU_HASH_MAP; template , class Equal_t = AuHash::equal> -using AuHashMapOfHeap = AuHashMap>>; +using AuHashMapOfHeap = AuHashMap>>; template struct AuIsHashMap : AuFalseType diff --git a/Include/auROXTL/auList.hpp b/Include/auROXTL/auList.hpp index a703def..daa9321 100644 --- a/Include/auROXTL/auList.hpp +++ b/Include/auROXTL/auList.hpp @@ -26,4 +26,4 @@ #endif template -using AuListOfHeap = AuList>; \ No newline at end of file +using AuListOfHeap = AuList>; \ No newline at end of file diff --git a/Include/auROXTL/auMemoryModel.hpp b/Include/auROXTL/auMemoryModel.hpp index 9d79c03..efe406d 100644 --- a/Include/auROXTL/auMemoryModel.hpp +++ b/Include/auROXTL/auMemoryModel.hpp @@ -12,6 +12,18 @@ #include "auTypes.hpp" +struct AuHeap; + +namespace __audetail +{ + extern AuHeap *gDefaultDiscontiguousHeap; +} + +namespace Aurora::Memory +{ + struct ProxyHeap; +} + #if !defined(AURORA_RUNTIME_AU_SHARED_PTR) #define AURORA_RUNTIME_AU_SHARED_PTR std::shared_ptr #endif @@ -24,15 +36,19 @@ template using AuWPtr = AURORA_RUNTIME_AU_WEAK_PTR; #if !defined(AURORA_RUNTIME_AU_UNIQUE_PTR) - #define AURORA_RUNTIME_AU_UNIQUE_PTR std::unique_ptr + #define AURORA_RUNTIME_AU_UNIQUE_PTR AuUniquePointer #endif +#include #include "STLShims/ExtendStlLikeSharedPtr.hpp" template using AuSPtr = typename Aurora::Memory::ExSharedPtr>; -template +template +using AuSSPtr = typename AURORA_RUNTIME_AU_SHARED_PTR; + +template using AuUPtr = AURORA_RUNTIME_AU_UNIQUE_PTR; #if !defined(AU_AuEnableSharedFromThis) @@ -99,13 +115,14 @@ static void auline AuSafeDelete(T *in) #define AURORA_RUNTIME_AU_DEFAULT_DELETER std::default_delete #endif +template +struct AuPMRAllocator; + namespace Aurora::Memory { template struct CppHeapWrapper; - template - struct PmrCppHeapWrapper; #if defined(AURORA_ROXTL_ALLOCATORS_USE_STD) @@ -306,31 +323,7 @@ namespace Aurora::Memory #endif template -static auline AuSPtr AuMakeShared(Args&&... args) -{ - using Z = AuRemoveConst_t; - - try - { - #if defined(AURORA_ROXTL_ALLOCATORS_USE_STD) - return AURORA_RUNTIME_MAKE_SHARED(AuForward(args)...); - #else - auto pNext = Aurora::Memory::__FAlloc(sizeof(T), alignof(T)); - if (!pNext) - { - return nullptr; - } - - auto pNextClass = (Z *)pNext; - new (pNextClass) Z (AuForward(args)...); - return std::shared_ptr(pNextClass, Aurora::Memory::DefaultRuntimeDeleter {}, Aurora::Memory::SharedControlBlockAllocator {}); - #endif - } - catch (...) - { - return {}; - } -} +AuSPtr AuMakeShared(Args&&... args); template static auline AuSPtr AuMakeSharedPanic(Args&&... args) @@ -418,17 +411,18 @@ namespace __audetail char a; }; + inline AuSPtr gDummy; + inline AuSPtr GetDummyDeleter() { - static AuSPtr d; - if (!d) + if (!gDummy) { #if defined(AURORA_COMPILER_MSVC) - return d; + return gDummy; #endif - d = AuMakeShared(); + gDummy = AuMakeShared(); } - return d; + return gDummy; } } @@ -458,4 +452,14 @@ inline constexpr bool operator!=(const Aurora::Memory::BaseAuroraRuntimeAllocato return false; } -#include \ No newline at end of file +#include + +#include + +#include +#include +#include + +#include + +#include \ No newline at end of file diff --git a/Include/auROXTLTypes.hpp b/Include/auROXTLTypes.hpp index 27577a2..4ffb6b4 100644 --- a/Include/auROXTLTypes.hpp +++ b/Include/auROXTLTypes.hpp @@ -169,6 +169,8 @@ namespace __audetail #include #include #include +#include +#include #include #include #include diff --git a/Include/auROXTLUtils.hpp b/Include/auROXTLUtils.hpp index 0de9a74..b193656 100644 --- a/Include/auROXTLUtils.hpp +++ b/Include/auROXTLUtils.hpp @@ -78,6 +78,10 @@ namespace __audetail #include +#include +#include +#include + struct IAuNullDelegate { virtual void OnCall() = 0;