Compare commits

..

2 Commits

Author SHA1 Message Date
8df3f6970b [+] Heap::Clone(Heap *[, ...]) 2024-07-15 00:16:13 +01:00
ced9e0be17 [*] Optimize global process heap aliases
[*] Split AuMemory::Heap impl into .inl file
2024-07-15 00:15:35 +01:00
5 changed files with 518 additions and 358 deletions

View File

@ -16,6 +16,16 @@ namespace Aurora::Memory
template <class T> template <class T>
struct CppHeapWrapper; struct CppHeapWrapper;
/**
* Note: The following public aliases for heap or global process heap based allocations exist:
*
* AuHUPOf_t<T> AuNewClassArrayUnique([pHeap, ]uElements, ...)
* AuSPtr<T> AuNewClassArray([pHeap, ]uElements, ...)
* AuHUPOf_t<T> AuNewClassUnique([pHeap, ] ...)
* AuSPtr<T> AuNewClass([pHeap, ] ...)
* AuHUPOf_t<T> AuNullHeapPointer<T>()
*/
struct Heap struct Heap
{ {
virtual AuSPtr<Heap> AllocateDivision(AuUInt32 heap, AuUInt32 alignment = 32) = 0; virtual AuSPtr<Heap> AllocateDivision(AuUInt32 heap, AuUInt32 alignment = 32) = 0;
@ -23,415 +33,103 @@ namespace Aurora::Memory
virtual HeapStats &GetStats() = 0; virtual HeapStats &GetStats() = 0;
virtual void WalkHeap(bool(*fCallback)(void *, void *), void *pSecondArg) = 0; virtual void WalkHeap(bool(*fCallback)(void *, void *), void *pSecondArg) = 0;
// Potentially slower, zero allocate /// Potentially slower, zero allocate
template<typename T = void *> template<typename T = void *>
T ZAlloc(Types::size_t uLength) T ZAlloc(Types::size_t uLength);
{
if constexpr (AuIsVoid_v<AuRemovePointer_t<T>>)
{
return reinterpret_cast<T>(_ZAlloc(uLength));
}
else
{
return reinterpret_cast<T>(_ZAlloc(uLength, alignof(AuRemovePointer_t<T>)));
}
}
/// POD zero allocation
template<typename T = void *> template<typename T = void *>
T ZAlloc(Types::size_t uLength, Types::size_t uAlignment) T ZAlloc(Types::size_t uLength, Types::size_t uAlignment);
{
return reinterpret_cast<T>(_ZAlloc(uLength, uAlignment));
}
/// POD zero allocation
template<typename T> template<typename T>
T *ZAlloc() T *ZAlloc();
{
return reinterpret_cast<T *>(_ZAlloc(sizeof(T), alignof(T)));
}
/// POD array, zero allocation
template<typename T> template<typename T>
T *NewArray(Types::size_t uLength) T *NewArray(Types::size_t uLength);
{
return ZAlloc<T *>(uLength * sizeof(T), alignof(T));
}
/// POD array, zero allocation
template<typename T> template<typename T>
T *NewArray(Types::size_t uLength, Types::size_t uAlignment) T *NewArray(Types::size_t uLength, Types::size_t uAlignment);
{
return ZAlloc<T *>(uLength * sizeof(T), uAlignment);
}
/// Fast, unsafe alloc /// Fast, POD, non-zeroing allocation
template<typename T = void *> template<typename T = void *>
T FAlloc(Types::size_t uLength) T FAlloc(Types::size_t uLength);
{
if constexpr (AuIsVoid_v<AuRemovePointer_t<T>>)
{
return reinterpret_cast<T>(_FAlloc(uLength));
}
else
{
return reinterpret_cast<T>(_FAlloc(uLength, alignof(AuRemovePointer_t<T>)));
}
}
/// Fast, POD, non-zeroing allocation
template<typename T = void *> template<typename T = void *>
T FAlloc(Types::size_t uLength, Types::size_t uAlignment) T FAlloc(Types::size_t uLength, Types::size_t uAlignment);
{
return reinterpret_cast<T>(_FAlloc(uLength, uAlignment));
}
/// Fast, POD, non-zeroing allocation
template<typename T> template<typename T>
T *FAlloc() T *FAlloc();
{
return reinterpret_cast<T *>(_FAlloc(sizeof(T), alignof(T)));
}
// Reallocs // Reallocs
template<typename T>
T ZRealloc(T pHead, Types::size_t uLength)
{
if constexpr (AuIsVoid_v<AuRemovePointer_t<T>>)
{
return reinterpret_cast<T>(_ZRealloc(reinterpret_cast<void *>(pHead), uLength));
}
else
{
return reinterpret_cast<T>(_ZRealloc(reinterpret_cast<void *>(pHead), uLength, alignof(AuRemovePointer_t<T>)));
}
}
/// POD, zero-based expansion or reallocation
template<typename T> template<typename T>
T ZRealloc(T pHead, Types::size_t uLength, Types::size_t uAlignment) T ZRealloc(T pHead, Types::size_t uLength);
{
return reinterpret_cast<T>(_ZRealloc(reinterpret_cast<void *>(pHead), uLength, uAlignment));
}
/// POD, zero-based expansion or reallocation
template<typename T> template<typename T>
T FRealloc(T pHead, Types::size_t uLength) T ZRealloc(T pHead, Types::size_t uLength, Types::size_t uAlignment);
{
if constexpr (AuIsVoid_v<AuRemovePointer_t<T>>)
{
return reinterpret_cast<T>(_FRealloc(reinterpret_cast<void *>(pHead), uLength));
}
else
{
return reinterpret_cast<T>(_FRealloc(reinterpret_cast<void *>(pHead), uLength, alignof(AuRemovePointer_t<T>)));
}
}
/// POD, expansion or reallocation
template<typename T> template<typename T>
T FRealloc(T pHead, Types::size_t uLength, Types::size_t uAlignment) T FRealloc(T pHead, Types::size_t uLength);
{
return reinterpret_cast<T>(_FRealloc(reinterpret_cast<void *>(pHead), uLength, uAlignment));
}
// Free /// POD, expansion or reallocation
template<typename T> template<typename T>
void Free(T pHead) T FRealloc(T pHead, Types::size_t uLength, Types::size_t uAlignment);
{
_Free(reinterpret_cast<void *>(pHead)); /// Free
} template<typename T>
void Free(T pHead);
protected: protected:
template <typename T> template <typename T>
static void DeleteThat(T *pThat) static void DeleteThat(T *pThat);
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *));
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyDestructible_v<T>)
{
pThat->~T();
}
auto &pHeap = *(Heap **)(((char *)pThat) - kAlignment);
pHeap->_Free(&pHeap);
}
template <typename T> template <typename T>
static void DeleteThatArray(T *pThat) static void DeleteThatArray(T *pThat);
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2);
auto pVoids = (void **)(((char *)pThat) - kAlignment);
auto pHeap = (Heap *)pVoids[0];
auto uLength = (AuUInt)pVoids[1];
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyDestructible_v<T>)
{
for (AU_ITERATE_N(i, uLength))
{
auto &refElement = pThat[i];
refElement.~T();
}
}
pHeap->_Free(pVoids);
}
template <typename T, typename Z> template <typename T, typename Z>
static void DeleteThatCastedOnce(T *pThat) static void DeleteThatCastedOnce(T *pThat);
{
static const auto kAlignment = AuMax(alignof(Z), sizeof(void *));
auto pBaseClass = AuStaticCast<Z>(pThat);
if constexpr (AuIsClass_v<Z> &&
!AuIsTriviallyDestructible_v<Z>)
{
pBaseClass->~Z();
}
auto &pHeap = *(Heap **)(((char *)pBaseClass) - kAlignment);
pHeap->_Free(&pHeap);
}
template <typename T> template <typename T>
static void RetardedSpecWrittenByRetards(T *pThat) static void RetardedSpecWrittenByRetards(T *pThat);
{
}
public: public:
template <class T, class ...Args> template <class T, class ...Args>
AuSPtr<T> NewClass(Args &&...args) AuSPtr<T> NewClass(Args &&...args);
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *));
AuUInt8 *pPtr;
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyConstructible_v<T, Args...>)
{
pPtr = pThat->FAlloc<AuUInt8 *>(sizeof(T) + kAlignment, kAlignment);
if (pPtr)
{
new (pPtr + kAlignment) T(AuForward<Args>(args)...);
}
}
else
{
pPtr = pThat->ZAlloc<AuUInt8 *>(sizeof(T) + kAlignment, kAlignment);
}
if (!pPtr)
{
return {};
}
*(void **)pPtr = pThat;
auto pTThat = (T *)(pPtr + kAlignment);
AUROXTL_COMMODITY_TRY
{
return AuSPtr<T>(pTThat, &Heap::DeleteThat<T>, CppHeapWrapper<T> { this });
}
AUROXTL_COMMODITY_CATCH
{
Heap::DeleteThat<T>(pTThat);
return {};
}
}
// note: callers can use AuHUPOf_t<Z> pUniquePointer = AuNullHeapPointer<Z>() // note: callers can use AuHUPOf_t<Z> pUniquePointer = AuNullHeapPointer<Z>()
template <class T, class Z = T, class ...Args> template <class T, class Z = T, class ...Args>
AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)> NewClassUnique(Args &&...args) AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)> NewClassUnique(Args &&...args);
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *));
AuUInt8 *pPtr;
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyConstructible_v<T, Args...>)
{
pPtr = pThat->FAlloc<AuUInt8 *>(sizeof(T) + kAlignment, kAlignment);
if (pPtr)
{
new (pPtr + kAlignment) T(AuForward<Args>(args)...);
}
}
else
{
pPtr = pThat->ZAlloc<AuUInt8 *>(sizeof(T) + kAlignment, kAlignment);
}
if (!pPtr)
{
return AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)>(nullptr, &Heap::RetardedSpecWrittenByRetards<Z>);
}
*(void **)pPtr = pThat;
if constexpr (AuIsSame_v<T, Z>)
{
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &Heap::DeleteThat<T>);
}
else
{
return Heap::CastPointer<Z>(AuMove(AuUPtr<T, decltype(&Heap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &Heap::DeleteThat<T>)));
}
}
template <class T, class ...Args> template <class T, class ...Args>
AuSPtr<T> NewClassArray(AuUInt uElements, Args &&... fillCtr) AuSPtr<T> NewClassArray(AuUInt uElements, Args &&... fillCtr);
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2);
AuUInt8 *pPtr;
if (!uElements) template <class T, class ...Args>
{ AuSPtr<T> NewClassArray2(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr);
return {};
}
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyConstructible_v<T, Args...>)
{
if (bool(pPtr = pThat->FAlloc<AuUInt8 *>((sizeof(T) * uElements) + kAlignment, kAlignment)))
{
for (AU_ITERATE_N(i, uElements))
{
new (pPtr + kAlignment + (sizeof(T) * i)) T(AuForward<Args>(fillCtr)...);
}
}
}
else
{
if (bool(pPtr = pThat->ZAlloc<AuUInt8 *>((sizeof(T) * uElements) + kAlignment, kAlignment)))
{
if constexpr (sizeof...(Args) != 0)
{
#if defined(AURT_HEAP_NO_STL)
static_assert(false);
#else
auto pElements = (T *)(pPtr + kAlignment);
std::fill(pElements, pElements + uElements, AuForward<Args>(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<T>(pTThat, &Heap::DeleteThatArray<T>, CppHeapWrapper<T> { this });
}
AUROXTL_COMMODITY_CATCH
{
Heap::DeleteThatArray<T>(pTThat);
return {};
}
}
// note: callers can use AuHUPOf_t<T> pUniquePointer = AuNullHeapPointer<T>() // note: callers can use AuHUPOf_t<T> pUniquePointer = AuNullHeapPointer<T>()
template <class T, class ...Args> template <class T, class ...Args>
AuUPtr<T, decltype(&Heap::DeleteThat<T>)> NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr) AuUPtr<T, decltype(&Heap::DeleteThat<T>)> NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr);
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2);
AuUInt8 *pPtr;
if (!uElements) template <class T, class ...Args>
{ AuUPtr<T, decltype(&Heap::DeleteThat<T>)> NewClassArray2Unique(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr);
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>(nullptr, &Heap::RetardedSpecWrittenByRetards<T>);
}
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyConstructible_v<T, Args...>)
{
if (bool(pPtr = pThat->FAlloc<AuUInt8 *>((sizeof(T) * uElements) + kAlignment, kAlignment)))
{
for (AU_ITERATE_N(i, uElements))
{
new (pPtr + kAlignment + (sizeof(T) * i)) T(AuForward<Args>(fillCtr)...);
}
}
}
else
{
if (bool(pPtr = pThat->ZAlloc<AuUInt8 *>((sizeof(T) * uElements) + kAlignment, kAlignment)))
{
if constexpr (sizeof...(Args) != 0)
{
#if defined(AURT_HEAP_NO_STL)
static_assert(false);
#else
auto pElements = (T *)(pPtr + kAlignment);
std::fill(pElements, pElements + uElements, AuForward<Args>(fillCtr)...);
#endif
}
}
}
if (!pPtr)
{
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>(nullptr, &Heap::RetardedSpecWrittenByRetards<T>);
}
auto pVoids = (void **)pPtr;
pVoids[0] = pThat;
pVoids[1] = (void *)uElements;
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &Heap::DeleteThatArray<T>);
}
template <class T> template <class T>
cstatic AuUPtr<T, decltype(&Heap::DeleteThat<T>)> NullUniquePointer() cstatic AuUPtr<T, decltype(&Heap::DeleteThat<T>)> NullUniquePointer();
{
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>(nullptr, &Heap::RetardedSpecWrittenByRetards<T>);
}
template <class Z, class T> template <class Z, class T>
cstatic AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)> CastPointer(AuUPtr<T, decltype(&Heap::DeleteThat<T>)> &&pInPointer) cstatic AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)> CastPointer(AuUPtr<T, decltype(&Heap::DeleteThat<T>)> &&pInPointer);
{
if (!pInPointer)
{
return NullUniquePointer<Z>();
}
else if (pInPointer.get_deleter() == &Heap::DeleteThat<T>)
{
return AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)>(AuStaticCast<Z>(pInPointer.release()), &Heap::DeleteThatCastedOnce<Z, T>);
}
else
{
return NullUniquePointer<Z>();
}
}
template <typename T> template <typename T>
using HUPOf_t = AuUPtr<T, decltype(&Heap::DeleteThat<T>)>; using HUPOf_t = AuUPtr<T, decltype(&Heap::DeleteThat<T>)>;

View File

@ -0,0 +1,432 @@
/***
Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Heap.inl
Date: 2024-7-14
Date: 2021-6-9
Author: Reece
***/
#pragma once
namespace Aurora::Memory
{
template<typename T>
T Heap::ZAlloc(Types::size_t uLength)
{
if constexpr (AuIsVoid_v<AuRemovePointer_t<T>>)
{
return reinterpret_cast<T>(_ZAlloc(uLength));
}
else
{
return reinterpret_cast<T>(_ZAlloc(uLength, alignof(AuRemovePointer_t<T>)));
}
}
template<typename T>
T Heap::ZAlloc(Types::size_t uLength, Types::size_t uAlignment)
{
return reinterpret_cast<T>(_ZAlloc(uLength, uAlignment));
}
template<typename T>
T *Heap::ZAlloc()
{
return reinterpret_cast<T *>(_ZAlloc(sizeof(T), alignof(T)));
}
template<typename T>
T *Heap::NewArray(Types::size_t uLength)
{
return ZAlloc<T *>(uLength * sizeof(T), alignof(T));
}
template<typename T>
T *Heap::NewArray(Types::size_t uLength, Types::size_t uAlignment)
{
return ZAlloc<T *>(uLength * sizeof(T), uAlignment);
}
template<typename T>
T Heap::FAlloc(Types::size_t uLength)
{
if constexpr (AuIsVoid_v<AuRemovePointer_t<T>>)
{
return reinterpret_cast<T>(_FAlloc(uLength));
}
else
{
return reinterpret_cast<T>(_FAlloc(uLength, alignof(AuRemovePointer_t<T>)));
}
}
template<typename T>
T Heap::FAlloc(Types::size_t uLength, Types::size_t uAlignment)
{
return reinterpret_cast<T>(_FAlloc(uLength, uAlignment));
}
template<typename T>
T *Heap::FAlloc()
{
return reinterpret_cast<T *>(_FAlloc(sizeof(T), alignof(T)));
}
// Reallocs
template<typename T>
T Heap::ZRealloc(T pHead, Types::size_t uLength)
{
if constexpr (AuIsVoid_v<AuRemovePointer_t<T>>)
{
return reinterpret_cast<T>(_ZRealloc(reinterpret_cast<void *>(pHead), uLength));
}
else
{
return reinterpret_cast<T>(_ZRealloc(reinterpret_cast<void *>(pHead), uLength, alignof(AuRemovePointer_t<T>)));
}
}
template<typename T>
T Heap::ZRealloc(T pHead, Types::size_t uLength, Types::size_t uAlignment)
{
return reinterpret_cast<T>(_ZRealloc(reinterpret_cast<void *>(pHead), uLength, uAlignment));
}
template<typename T>
T Heap::FRealloc(T pHead, Types::size_t uLength)
{
if constexpr (AuIsVoid_v<AuRemovePointer_t<T>>)
{
return reinterpret_cast<T>(_FRealloc(reinterpret_cast<void *>(pHead), uLength));
}
else
{
return reinterpret_cast<T>(_FRealloc(reinterpret_cast<void *>(pHead), uLength, alignof(AuRemovePointer_t<T>)));
}
}
template<typename T>
T Heap::FRealloc(T pHead, Types::size_t uLength, Types::size_t uAlignment)
{
return reinterpret_cast<T>(_FRealloc(reinterpret_cast<void *>(pHead), uLength, uAlignment));
}
// Free
template<typename T>
void Heap::Free(T pHead)
{
_Free(reinterpret_cast<void *>(pHead));
}
template <typename T>
void Heap::DeleteThat(T *pThat)
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *));
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyDestructible_v<T>)
{
pThat->~T();
}
auto &pHeap = *(Heap **)(((char *)pThat) - kAlignment);
pHeap->_Free(&pHeap);
}
template <typename T>
void Heap::DeleteThatArray(T *pThat)
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2);
auto pVoids = (void **)(((char *)pThat) - kAlignment);
auto pHeap = (Heap *)pVoids[0];
auto uLength = (AuUInt)pVoids[1];
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyDestructible_v<T>)
{
for (AU_ITERATE_N(i, uLength))
{
auto &refElement = pThat[i];
refElement.~T();
}
}
pHeap->_Free(pVoids);
}
template <typename T, typename Z>
void Heap::DeleteThatCastedOnce(T *pThat)
{
static const auto kAlignment = AuMax(alignof(Z), sizeof(void *));
auto pBaseClass = AuStaticCast<Z>(pThat);
if constexpr (AuIsClass_v<Z> &&
!AuIsTriviallyDestructible_v<Z>)
{
pBaseClass->~Z();
}
auto &pHeap = *(Heap **)(((char *)pBaseClass) - kAlignment);
pHeap->_Free(&pHeap);
}
template <typename T>
static void Heap::RetardedSpecWrittenByRetards(T *pThat)
{
}
template <class T, class ...Args>
AuSPtr<T> Heap::NewClass(Args &&...args)
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *));
AuUInt8 *pPtr;
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyConstructible_v<T, Args...>)
{
pPtr = pThat->FAlloc<AuUInt8 *>(sizeof(T) + kAlignment, kAlignment);
if (pPtr)
{
new (pPtr + kAlignment) T(AuForward<Args>(args)...);
}
}
else
{
pPtr = pThat->ZAlloc<AuUInt8 *>(sizeof(T) + kAlignment, kAlignment);
}
if (!pPtr)
{
return {};
}
*(void **)pPtr = pThat;
auto pTThat = (T *)(pPtr + kAlignment);
AUROXTL_COMMODITY_TRY
{
return AuSPtr<T>(pTThat, &Heap::DeleteThat<T>, CppHeapWrapper<T> { this });
}
AUROXTL_COMMODITY_CATCH
{
Heap::DeleteThat<T>(pTThat);
return {};
}
}
template <class T, class Z, class ...Args>
AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)> Heap::NewClassUnique(Args &&...args)
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *));
AuUInt8 *pPtr;
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyConstructible_v<T, Args...>)
{
pPtr = pThat->FAlloc<AuUInt8 *>(sizeof(T) + kAlignment, kAlignment);
if (pPtr)
{
new (pPtr + kAlignment) T(AuForward<Args>(args)...);
}
}
else
{
pPtr = pThat->ZAlloc<AuUInt8 *>(sizeof(T) + kAlignment, kAlignment);
}
if (!pPtr)
{
return AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)>(nullptr, &Heap::RetardedSpecWrittenByRetards<Z>);
}
*(void **)pPtr = pThat;
if constexpr (AuIsSame_v<T, Z>)
{
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &Heap::DeleteThat<T>);
}
else
{
return Heap::CastPointer<Z>(AuMove(AuUPtr<T, decltype(&Heap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &Heap::DeleteThat<T>)));
}
}
template <class T, class ...Args>
AuSPtr<T> Heap::NewClassArray(AuUInt uElements, Args &&... fillCtr)
{
return NewClassArray2<T, Args...>(uElements, alignof(T), AuForward<Args>(fillCtr)...);
}
template <class T, class ...Args>
AuSPtr<T> Heap::NewClassArray2(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr)
{
const auto kAlignment = AuMax(uAlignment, sizeof(void *) * 2);
AuUInt8 *pPtr;
if (!uElements)
{
return {};
}
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyConstructible_v<T, Args...>)
{
if (bool(pPtr = pThat->FAlloc<AuUInt8 *>((sizeof(T) * uElements) + kAlignment, kAlignment)))
{
for (AU_ITERATE_N(i, uElements))
{
new (pPtr + kAlignment + (sizeof(T) * i)) T(AuForward<Args>(fillCtr)...);
}
}
}
else
{
if (bool(pPtr = pThat->ZAlloc<AuUInt8 *>((sizeof(T) * uElements) + kAlignment, kAlignment)))
{
if constexpr (sizeof...(Args) != 0)
{
#if defined(AURT_HEAP_NO_STL)
static_assert(false);
#else
auto pElements = (T *)(pPtr + kAlignment);
std::fill(pElements, pElements + uElements, AuForward<Args>(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<T>(pTThat, &Heap::DeleteThatArray<T>, CppHeapWrapper<T> { this });
}
AUROXTL_COMMODITY_CATCH
{
Heap::DeleteThatArray<T>(pTThat);
return {};
}
}
template <class T, class ...Args>
AuUPtr<T, decltype(&Heap::DeleteThat<T>)> Heap::NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr)
{
return NewClassArray2Unique<T, Args...>(uElements, alignof(T), AuForward<Args>(fillCtr)...);
}
template <class T, class ...Args>
AuUPtr<T, decltype(&Heap::DeleteThat<T>)> Heap::NewClassArray2Unique(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr)
{
const auto kAlignment = AuMax(uAlignment, sizeof(void *) * 2);
AuUInt8 *pPtr;
if (!uElements)
{
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>(nullptr, &Heap::RetardedSpecWrittenByRetards<T>);
}
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyConstructible_v<T, Args...>)
{
if (bool(pPtr = pThat->FAlloc<AuUInt8 *>((sizeof(T) * uElements) + kAlignment, kAlignment)))
{
for (AU_ITERATE_N(i, uElements))
{
new (pPtr + kAlignment + (sizeof(T) * i)) T(AuForward<Args>(fillCtr)...);
}
}
}
else
{
if (bool(pPtr = pThat->ZAlloc<AuUInt8 *>((sizeof(T) * uElements) + kAlignment, kAlignment)))
{
if constexpr (sizeof...(Args) != 0)
{
#if defined(AURT_HEAP_NO_STL)
static_assert(false);
#else
auto pElements = (T *)(pPtr + kAlignment);
std::fill(pElements, pElements + uElements, AuForward<Args>(fillCtr)...);
#endif
}
}
}
if (!pPtr)
{
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>(nullptr, &Heap::RetardedSpecWrittenByRetards<T>);
}
auto pVoids = (void **)pPtr;
pVoids[0] = pThat;
pVoids[1] = (void *)uElements;
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &Heap::DeleteThatArray<T>);
}
template <class T>
AuUPtr<T, decltype(&Heap::DeleteThat<T>)> Heap::NullUniquePointer()
{
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>(nullptr, &Heap::RetardedSpecWrittenByRetards<T>);
}
template <class Z, class T>
AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)> Heap::CastPointer(AuUPtr<T, decltype(&Heap::DeleteThat<T>)> &&pInPointer)
{
if (!pInPointer)
{
return NullUniquePointer<Z>();
}
else if (pInPointer.get_deleter() == &Heap::DeleteThat<T>)
{
return AuUPtr<Z, decltype(&Heap::DeleteThat<Z>)>(AuStaticCast<Z>(pInPointer.release()), &Heap::DeleteThatCastedOnce<Z, T>);
}
else
{
return NullUniquePointer<Z>();
}
}
namespace detail
{
inline AuSPtr<AuUInt8> AllocateArray(Heap *pHeap, AuUInt uLength, AuUInt32 uAlignment)
{
return pHeap->NewClassArray2<AuUInt8>(uLength, uAlignment);
}
}
}

View File

@ -197,3 +197,4 @@ namespace Aurora::Memory
#include "ByteBuffer.hpp" #include "ByteBuffer.hpp"
#include "ByteBufferPushReadState.hpp" #include "ByteBufferPushReadState.hpp"
#include "ByteBufferPushWriteState.hpp" #include "ByteBufferPushWriteState.hpp"
#include "Heap.inl"

View File

@ -9,6 +9,13 @@
namespace Aurora::Memory namespace Aurora::Memory
{ {
struct Heap;
namespace detail
{
inline AuSPtr<AuUInt8> AllocateArray(Heap *pHeap, AuUInt uLength, AuUInt32 uAlignment);
}
struct MemoryControlBlock struct MemoryControlBlock
{ {
// Free-after-use mitigator: ensures a non-zero flag is kept whilst other memory views are present // Free-after-use mitigator: ensures a non-zero flag is kept whilst other memory views are present
@ -392,6 +399,19 @@ namespace Aurora::Memory
return MemoryView(MemoryView(pData.get(), uLength), pData); return MemoryView(MemoryView(pData.get(), uLength), pData);
} }
MemoryView Clone(Heap *pHeap, AuUInt32 uAlignment = alignof(double)) const
{
auto uLength = this->uLength;
auto pData = detail::AllocateArray(uLength, uAlignment);
if (!pData)
{
return {};
}
AuMemcpy(pData.get(), this->pBase, uLength);
return MemoryView(MemoryView(pData.get(), uLength), pData);
}
bool TryCloneSelf(bool bResetOnFailure = true) bool TryCloneSelf(bool bResetOnFailure = true)
{ {
auto replacement = Clone(); auto replacement = Clone();

View File

@ -142,28 +142,37 @@ auto AuNullPointer()
return Aurora::Memory::Heap::NullUniquePointer<T>(); return Aurora::Memory::Heap::NullUniquePointer<T>();
} }
namespace __audetail
{
inline AuMemory::Heap *gDefaultDiscontiguousHeap = AuMemory::GetDefaultDiscontiguousHeap();
}
template <class T, class ...Args> template <class T, class ...Args>
AuHUPOf_t<T> AuNewClassArrayUnique(AuUInt uElements, Args &&... fillCtr) AuHUPOf_t<T> AuNewClassArrayUnique(AuUInt uElements, Args &&... fillCtr)
{ {
return Aurora::Memory::GetDefaultDiscontiguousHeap()->NewClassArrayUnique<T, Args...>(uElements, AuForward<Args>(fillCtr)...); return __audetail::gDefaultDiscontiguousHeap->NewClassArrayUnique<T, Args...>(uElements, AuForward<Args>(fillCtr)...);
} }
template <class T, class ...Args> template <class T, class ...Args>
AuSPtr<T> AuNewClassArray(AuUInt uElements, Args &&... fillCtr) AuSPtr<T> AuNewClassArray(AuUInt uElements, Args &&... fillCtr)
{ {
return Aurora::Memory::GetDefaultDiscontiguousHeap()->NewClassArray<T, Args...>(uElements, AuForward<Args>(fillCtr)...); return __audetail::gDefaultDiscontiguousHeap->NewClassArray<T, Args...>(uElements, AuForward<Args>(fillCtr)...);
} }
template <class T, class Z = T, class ...Args> template <class T, class Z = T, class ...Args>
AuHUPOf_t<Z> AuNewClassUnique(Args &&...args) AuHUPOf_t<Z> AuNewClassUnique(Args &&...args)
{ {
return Aurora::Memory::GetDefaultDiscontiguousHeap()->NewClassUnique<T, Z, Args...>(AuForward<Args>(args)...); return __audetail::gDefaultDiscontiguousHeap->NewClassUnique<T, Z, Args...>(AuForward<Args>(args)...);
} }
template <class T, class ...Args> template <class T, class ...Args>
AuSPtr<T> AuNewClass(Args &&...args) AuSPtr<T> AuNewClass(Args &&...args)
{ {
#if !defined(AURORA_RUNTIME_HEADERS_ALWAYS_LOOKUP_HEAP)
return AuMakeShared<T, Args...>(AuForward<Args>(args)...);
#else
return Aurora::Memory::GetDefaultDiscontiguousHeap()->NewClass<T, Args...>(AuForward<Args>(args)...); return Aurora::Memory::GetDefaultDiscontiguousHeap()->NewClass<T, Args...>(AuForward<Args>(args)...);
#endif
} }
template <class T, class ...Args> template <class T, class ...Args>