[*] Fixup half-assed/rushed alloc class with alignment in the .hpp to .inl breakout commit (ced9e0be)

(sure, it cannot work to realign structs with c++ operator[] overloading; however, we need this to prevent excessive allocations when cloning a U8 memory view of alignment)
This commit is contained in:
Reece Wilson 2024-07-19 08:58:22 +01:00
parent 2628784ff6
commit a995c37e81
2 changed files with 151 additions and 14 deletions

View File

@ -95,6 +95,9 @@ namespace Aurora::Memory
template <typename T> template <typename T>
static void DeleteThatArray(T *pThat); static void DeleteThatArray(T *pThat);
template <typename T>
static void DeleteThatArray2(T *pThat);
template <typename T, typename Z> template <typename T, typename Z>
static void DeleteThatCastedOnce(T *pThat); static void DeleteThatCastedOnce(T *pThat);

View File

@ -155,6 +155,27 @@ namespace Aurora::Memory
pHeap->_Free(pVoids); pHeap->_Free(pVoids);
} }
template <typename T>
void Heap::DeleteThatArray2(T *pThat)
{
auto pBase = ((void **)pThat)[-1];
auto pVoids = (void **)pBase;
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>
void Heap::DeleteThatCastedOnce(T *pThat) void Heap::DeleteThatCastedOnce(T *pThat)
{ {
@ -269,13 +290,7 @@ namespace Aurora::Memory
template <class T, class ...Args> template <class T, class ...Args>
AuSPtr<T> Heap::NewClassArray(AuUInt uElements, Args &&... fillCtr) AuSPtr<T> Heap::NewClassArray(AuUInt uElements, Args &&... fillCtr)
{ {
return NewClassArray2<T, Args...>(uElements, alignof(T), AuForward<Args>(fillCtr)...); const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2);
}
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; AuUInt8 *pPtr;
if (!uElements) if (!uElements)
@ -338,15 +353,75 @@ namespace Aurora::Memory
} }
template <class T, class ...Args> template <class T, class ...Args>
AuUPtr<T, decltype(&Heap::DeleteThat<T>)> Heap::NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr) AuSPtr<T> Heap::NewClassArray2(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr)
{ {
return NewClassArray2Unique<T, Args...>(uElements, alignof(T), AuForward<Args>(fillCtr)...); const auto kAlignment = AuMax(uAlignment, sizeof(void *) * 4);
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;
((void **)(pPtr + kAlignment))[-1] = pPtr;
auto pTThat = (T *)(pPtr + kAlignment);
AUROXTL_COMMODITY_TRY
{
return AuSPtr<T>(pTThat, &Heap::DeleteThatArray2<T>, CppHeapWrapper<T> { this });
}
AUROXTL_COMMODITY_CATCH
{
Heap::DeleteThatArray2<T>(pTThat);
return {};
}
} }
template <class T, class ...Args> template <class T, class ...Args>
AuUPtr<T, decltype(&Heap::DeleteThat<T>)> Heap::NewClassArray2Unique(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr) AuUPtr<T, decltype(&Heap::DeleteThat<T>)> Heap::NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr)
{ {
const auto kAlignment = AuMax(uAlignment, sizeof(void *) * 2); const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2);
AuUInt8 *pPtr; AuUInt8 *pPtr;
if (!uElements) if (!uElements)
@ -399,6 +474,65 @@ namespace Aurora::Memory
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &Heap::DeleteThatArray<T>); return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &Heap::DeleteThatArray<T>);
} }
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 *) * 4);
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;
((void **)(pPtr + kAlignment))[-1] = pPtr;
auto pTThat = (T *)(pPtr + kAlignment);
return AuUPtr<T, decltype(&Heap::DeleteThat<T>)>(pTThat, &Heap::DeleteThatArray2<T>);
}
template <class T> template <class T>
AuUPtr<T, decltype(&Heap::DeleteThat<T>)> Heap::NullUniquePointer() AuUPtr<T, decltype(&Heap::DeleteThat<T>)> Heap::NullUniquePointer()
{ {