[*] Move assets from Runtime to ROXTL

[+] AuMemoryViewRead
[+] AuMemoryViewWrite
[+] AuMemoryViewStreamXXX
[+] SOO UniqueOnHeap
[+] SOO SharedOnHeap
[+] AuHeap
[+] AuHeapStats
[+] New implementation of AuUPtr<T>
This commit is contained in:
Reece Wilson 2024-09-13 08:50:25 +01:00
parent 0b8fbafdca
commit 11bb77f129
24 changed files with 2521 additions and 73 deletions

View File

@ -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<type, CppDeleter ## name>; \
using name ## Unique_t = AuUPtr<type>; \
template <class ... T> \
name ## Unique_t name ## Unique(T &&... args) \
{ \
return name ## Unique_t(name ## New(AuForward<T &&>(args)...)); \
return name ## Unique_t(name ## New(AuForward<T &&>(args)...), name ## Release); \
} \
\
using name ## Shared_t = AuSPtr<type>; \

View File

@ -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

View File

@ -0,0 +1 @@
// TODO:

View File

@ -0,0 +1 @@
// TODO:

View File

@ -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<T> AuNewClassArrayUnique([pHeap, ]uElements, ...)
* AuSPtr<T> AuNewClassArray([pHeap, ]uElements, ...)
* AuHUPOf_t<T> AuNewClassUnique([pHeap, ] ...)
* AuSPtr<T> AuNewClass([pHeap, ] ...)
* AuHUPOf_t<T> AuNullHeapPointer<T>()
*/
struct AuHeap
{
virtual AuSPtr<AuHeap> 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<typename T = void *>
T ZAlloc(AuUInt uLength);
/// POD zero allocation
template<typename T = void *>
T ZAlloc(AuUInt uLength, AuUInt uAlignment);
/// POD zero allocation
template<typename T>
T *ZAlloc();
/// POD array, zero allocation
template<typename T>
T *NewArray(AuUInt uLength);
/// POD array, zero allocation
template<typename T>
T *NewArray(AuUInt uLength, AuUInt uAlignment);
/// Fast, POD, non-zeroing allocation
template<typename T = void *>
T FAlloc(AuUInt uLength);
/// Fast, POD, non-zeroing allocation
template<typename T = void *>
T FAlloc(AuUInt uLength, AuUInt uAlignment);
/// Fast, POD, non-zeroing allocation
template<typename T>
T *FAlloc();
// Reallocs
/// POD, zero-based expansion or reallocation
template<typename T>
T ZRealloc(T pHead, AuUInt uLength);
/// POD, zero-based expansion or reallocation
template<typename T>
T ZRealloc(T pHead, AuUInt uLength, AuUInt uAlignment);
/// POD, expansion or reallocation
template<typename T>
T FRealloc(T pHead, AuUInt uLength);
/// POD, expansion or reallocation
template<typename T>
T FRealloc(T pHead, AuUInt uLength, AuUInt uAlignment);
/// Free
template<typename T>
void Free(T pHead);
protected:
template <typename T>
static void DeleteThat(T *pThat);
template <typename T>
static void DeleteThatArray(T *pThat);
template <typename T>
static void DeleteThatArray2(T *pThat);
template <typename T, typename Z>
static void DeleteThatCastedOnce(T *pThat);
template <typename T>
static void RetardedSpecWrittenByRetards(T *pThat);
public:
template <class T, class ...Args>
AuSPtr<T> NewClass(Args &&...args);
// note: callers can use AuHUPOf_t<Z> pUniquePointer = AuNullHeapPointer<Z>()
// update: no longer required with memory model update 2024/09
// AuHUPOf_t<T> or AuUPtr<T> will do
template <class T, class Z /* cast to */ = T, class ...Args>
AuUPtr<Z, decltype(&AuHeap::DeleteThat<Z>)> NewClassUnique(Args &&...args);
template <class T, class ...Args>
AuSPtr<T> 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 <class T, class ...Args>
AuSPtr<T> NewClassArray2(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr);
// note: callers can use AuHUPOf_t<T> pUniquePointer = AuNullHeapPointer<T>()
// update: no longer required with memory model update 2024/09
// AuHUPOf_t<T> or AuUPtr<T> will do
template <class T, class ...Args>
AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)> NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr);
template <class T, class ...Args>
AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)> NewClassArray2Unique(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr);
template <class T>
cstatic AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)> NullUniquePointer();
template <class Z, class T>
cstatic AuUPtr<Z, decltype(&AuHeap::DeleteThat<Z>)> CastPointer(AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)> &&pInPointer);
template <typename T>
using HUPOf_t = AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)>;
protected:
friend struct AuHeapAccessor;
friend struct Aurora::Memory::ProxyHeap;
virtual AuSPtr<AuHeap> 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;
};

View File

@ -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<typename T>
T AuHeap::ZAlloc(AuUInt 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 AuHeap::ZAlloc(AuUInt uLength, AuUInt uAlignment)
{
return reinterpret_cast<T>(_ZAlloc(uLength, uAlignment));
}
template<typename T>
T *AuHeap::ZAlloc()
{
return reinterpret_cast<T *>(_ZAlloc(sizeof(T), alignof(T)));
}
template<typename T>
T *AuHeap::NewArray(AuUInt uLength)
{
return ZAlloc<T *>(uLength * sizeof(T), alignof(T));
}
template<typename T>
T *AuHeap::NewArray(AuUInt uLength, AuUInt uAlignment)
{
return ZAlloc<T *>(uLength * sizeof(T), uAlignment);
}
template<typename T>
T AuHeap::FAlloc(AuUInt 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 AuHeap::FAlloc(AuUInt uLength, AuUInt uAlignment)
{
return reinterpret_cast<T>(_FAlloc(uLength, uAlignment));
}
template<typename T>
T *AuHeap::FAlloc()
{
return reinterpret_cast<T *>(_FAlloc(sizeof(T), alignof(T)));
}
// Reallocs
template<typename T>
T AuHeap::ZRealloc(T pHead, AuUInt 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 AuHeap::ZRealloc(T pHead, AuUInt uLength, AuUInt uAlignment)
{
return reinterpret_cast<T>(_ZRealloc(reinterpret_cast<void *>(pHead), uLength, uAlignment));
}
template<typename T>
T AuHeap::FRealloc(T pHead, AuUInt 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 AuHeap::FRealloc(T pHead, AuUInt uLength, AuUInt uAlignment)
{
return reinterpret_cast<T>(_FRealloc(reinterpret_cast<void *>(pHead), uLength, uAlignment));
}
// Free
template<typename T>
void AuHeap::Free(T pHead)
{
_Free(reinterpret_cast<void *>(pHead));
}
template <typename T>
void AuHeap::DeleteThat(T *pThat)
{
static const auto kAlignment = AuMax(alignof(T), sizeof(void *));
if constexpr (AuIsClass_v<T> &&
!AuIsTriviallyDestructible_v<T>)
{
pThat->~T();
}
auto &pAuHeap = *(AuHeap **)(((char *)pThat) - kAlignment);
pAuHeap->_Free(&pAuHeap);
}
template <typename T>
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<T> &&
!AuIsTriviallyDestructible_v<T>)
{
for (AU_ITERATE_N(i, uLength))
{
auto &refElement = pThat[i];
refElement.~T();
}
}
pAuHeap->_Free(pVoids);
}
template <typename T>
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<T> &&
!AuIsTriviallyDestructible_v<T>)
{
for (AU_ITERATE_N(i, uLength))
{
auto &refElement = pThat[i];
refElement.~T();
}
}
pAuHeap->_Free(pVoids);
}
template <typename T, typename Z>
void AuHeap::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 &pAuHeap = *(AuHeap **)(((char *)pBaseClass) - kAlignment);
pAuHeap->_Free(&pAuHeap);
}
template <typename T>
void AuHeap::RetardedSpecWrittenByRetards(T *pThat)
{
}
template <class T, class ...Args>
AuSPtr<T> 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<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, &AuHeap::DeleteThat<T>, AuPMRAllocator<T> { this });
}
AUROXTL_COMMODITY_CATCH
{
AuHeap::DeleteThat<T>(pTThat);
return {};
}
}
template <class T, class Z, class ...Args>
AuUPtr<Z, decltype(&AuHeap::DeleteThat<Z>)> 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<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(&AuHeap::DeleteThat<Z>)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards<Z>);
}
*(void **)pPtr = pThat;
if constexpr (AuIsSame_v<T, Z>)
{
return AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &AuHeap::DeleteThat<T>);
}
else
{
return AuHeap::CastPointer<Z>(AuMove(AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &AuHeap::DeleteThat<T>)));
}
}
template <class T, class ...Args>
AuSPtr<T> 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<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_AuHeap_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, &AuHeap::DeleteThatArray<T>, AuPMRAllocator<T> { this });
}
AUROXTL_COMMODITY_CATCH
{
AuHeap::DeleteThatArray<T>(pTThat);
return {};
}
}
template <class T, class ...Args>
AuSPtr<T> 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<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_AuHeap_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, &AuHeap::DeleteThatArray2<T>, AuPMRAllocator<T> { this });
}
AUROXTL_COMMODITY_CATCH
{
AuHeap::DeleteThatArray2<T>(pTThat);
return {};
}
}
template <class T, class ...Args>
AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)> AuHeap::NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr)
{
const auto kAlignment = AuMax(alignof(T), sizeof(void *) * 2);
AuUInt8 *pPtr;
if (!uElements)
{
return AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards<T>);
}
#if defined(AURORA_PROXYHEAP_REF_BASE_UAF)
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
#else
auto pThat = this;
#endif
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_AuHeap_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(&AuHeap::DeleteThat<T>)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards<T>);
}
auto pVoids = (void **)pPtr;
pVoids[0] = pThat;
pVoids[1] = (void *)uElements;
return AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)>((T *)(pPtr + kAlignment), &AuHeap::DeleteThatArray<T>);
}
template <class T, class ...Args>
AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)> AuHeap::NewClassArray2Unique(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr)
{
const auto kAlignment = AuMax(uAlignment, sizeof(void *) * 4);
AuUInt8 *pPtr;
if (!uElements)
{
return AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards<T>);
}
#if defined(AURORA_PROXYHEAP_REF_BASE_UAF)
auto pThat = this->GetSelfReferenceRaw();
if (!pThat)
{
pThat = this;
}
#else
auto pThat = this;
#endif
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_AuHeap_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(&AuHeap::DeleteThat<T>)>(nullptr, &AuHeap::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(&AuHeap::DeleteThat<T>)>(pTThat, &AuHeap::DeleteThatArray2<T>);
}
template <class T>
AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)> AuHeap::NullUniquePointer()
{
return AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)>(nullptr, &AuHeap::RetardedSpecWrittenByRetards<T>);
}
template <class Z, class T>
AuUPtr<Z, decltype(&AuHeap::DeleteThat<Z>)> AuHeap::CastPointer(AuUPtr<T, decltype(&AuHeap::DeleteThat<T>)> &&pInPointer)
{
if (!pInPointer)
{
return NullUniquePointer<Z>();
}
else if (pInPointer.get_deleter() == &AuHeap::DeleteThat<T>)
{
return AuUPtr<Z, decltype(&AuHeap::DeleteThat<Z>)>(AuStaticCast<Z>(pInPointer.release()), &AuHeap::DeleteThatCastedOnce<Z, T>);
}
else
{
return NullUniquePointer<Z>();
}
}
namespace __audetail
{
inline AuSPtr<AuUInt8> AllocateArray(AuHeap *pAuHeap, AuUInt uLength, AuUInt32 uAlignment)
{
return pAuHeap->NewClassArray2<AuUInt8>(uLength, uAlignment);
}
}

View File

@ -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<AuHeap> GetSelfReference(AuHeap *pHeap)
{
return pHeap->GetSelfReference();
}
cstatic AuHeap *GetSelfReferenceRaw(AuHeap *pHeap)
{
return pHeap->GetSelfReferenceRaw();
}
};

View File

@ -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 {};
};

View File

@ -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 <class T, typename... Args>
auline AuSPtr<T> AuMakeShared(Args &&... args)
{
using Z = AuRemoveConst_t<T>;
#if !defined(AURORA_RUNTIME_HEADERS_ALWAYS_LOOKUP_HEAP)
try
{
#if defined(AURORA_ROXTL_ALLOCATORS_USE_STD)
return AURORA_RUNTIME_MAKE_SHARED<T>(AuForward<Args>(args)...);
#else
auto pNext = Aurora::Memory::__FAlloc(sizeof(T), alignof(T));
if (!pNext)
{
return nullptr;
}
auto pNextClass = (Z *)pNext;
new (pNextClass) Z (AuForward<Args>(args)...);
return AuSSPtr<T>(pNextClass, Aurora::Memory::DefaultRuntimeDeleter<Z> {}, Aurora::Memory::SharedControlBlockAllocator<T> {});
#endif
}
catch (...)
{
return {};
}
#else
return __audetail::gDefaultDiscontiguousHeap->NewClass<Z, Args...>(AuForward<Args>(args)...);
#endif
}
template <typename T>
using AuHUPOf_t = AuUPtr<T, void(*)(T *)>;
template <class T>
auto AuNullHeapPointer()
{
return AuHeapNullUniquePointer<T>();
}
template <class T>
auto AuNullPointer()
{
return AuHeapNullUniquePointer<T>();
}
template <class T, class ...Args>
AuHUPOf_t<T> AuNewClassArrayUnique(AuUInt uElements, Args &&... fillCtr)
{
return __audetail::gDefaultDiscontiguousHeap->NewClassArrayUnique<T, Args...>(uElements, AuForward<Args>(fillCtr)...);
}
template <class T, class ...Args>
AuSPtr<T> AuNewClassArray(AuUInt uElements, Args &&... fillCtr)
{
return __audetail::gDefaultDiscontiguousHeap->NewClassArray<T, Args...>(uElements, AuForward<Args>(fillCtr)...);
}
template <class T, class Z = T, class ...Args>
AuHUPOf_t<Z> AuNewClassUnique(Args &&...args)
{
return __audetail::gDefaultDiscontiguousHeap->NewClassUnique<T, Z, Args...>(AuForward<Args>(args)...);
}
template <class T, class ...Args>
AuSPtr<T> AuNewClass(Args &&...args)
{
#if !defined(AURORA_RUNTIME_HEADERS_ALWAYS_LOOKUP_HEAP)
return AuMakeShared<T, Args...>(AuForward<Args>(args)...);
#else
return __audetail::gDefaultDiscontiguousHeap->NewClass<T, Args...>(AuForward<Args>(args)...);
#endif
}
template <class T, class ...Args>
AuHUPOf_t<T> AuNewClassArrayUnique(AuHeap *pHeap, AuUInt uElements, Args &&... fillCtr)
{
return pHeap->NewClassArrayUnique<T, Args...>(uElements, AuForward<Args>(fillCtr)...);
}
template <class T, class ...Args>
AuSPtr<T> AuNewClassArray(AuHeap *pHeap, AuUInt uElements, Args &&... fillCtr)
{
return pHeap->NewClassArray<T, Args...>(uElements, AuForward<Args>(fillCtr)...);
}
template <class T, class ...Args>
AuHUPOf_t<T> AuNewClassUnique(AuHeap *pHeap, Args &&...args)
{
return pHeap->NewClassUnique<T, Args...>(AuForward<Args>(args)...);
}
template <class T, class ...Args>
AuSPtr<T> AuNewClass(AuHeap *pHeap, Args &&...args)
{
return pHeap->NewClass<T, Args...>(AuForward<Args>(args)...);
}
template <class T, class ...Args>
AuHUPOf_t<T> AuNewClassArrayUnique(const AuSPtr<AuHeap> &pHeap, AuUInt uElements, Args &&... fillCtr)
{
return pHeap->NewClassArrayUnique<T, Args...>(uElements, AuForward<Args>(fillCtr)...);
}
template <class T, class ...Args>
AuSPtr<T> AuNewClassArray(const AuSPtr<AuHeap> &pHeap, AuUInt uElements, Args &&... fillCtr)
{
return pHeap->NewClassArray<T, Args...>(uElements, AuForward<Args>(fillCtr)...);
}
template <class T, class Z = T, class ...Args>
AuHUPOf_t<Z> AuNewClassUnique(const AuSPtr<AuHeap> &pHeap, Args &&...args)
{
return pHeap->NewClassUnique<T, Z, Args...>(AuForward<Args>(args)...);
}
template <class T, class ...Args>
AuSPtr<T> AuNewClass(const AuSPtr<AuHeap> &pHeap, Args &&...args)
{
return pHeap->NewClass<T, Args...>(AuForward<Args>(args)...);
}
template <class Z, class T>
AuHUPOf_t<Z> AuCastPointer(AuHUPOf_t<T> &&pInPointer)
{
// TODO: we can do better with this memory model update
return AuHeapCastPointer<Z>(AuMove(pInPointer));
}

View File

@ -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<void> 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<bool Readonly_b>
struct AuMemoryView
{
using U8_t = AuConditional_t<Readonly_b, const AuUInt8 *, AuUInt8 *>;
using Void_t = AuConditional_t<Readonly_b, const void *, void *>;
constexpr AuMemoryView();
template<typename T, AU_TEMPLATE_ENABLE_WHEN(AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, T>::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<void> &pThat,
void *pCallbackHandle = nullptr,
void (*pfCallbackOnZero)(void *) = nullptr);
constexpr AuMemoryView(AuMemoryView &&view);
template<typename T, int Z>
constexpr AuMemoryView(T(&a)[Z]);
template<typename T, int Z>
constexpr AuMemoryView(AuArray<T, Z> &view);
template<typename T>
constexpr AuMemoryView(T *start, T *end);
template<typename T>
constexpr AuMemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, void *pCallbackHandle = nullptr, void (*pfCallbackOnZero)(void *) = nullptr);
template<typename T>
constexpr AuMemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, const AuSPtr<void> &pRAIIOwner, void *pCallbackHandle = nullptr, void (*pfCallbackOnZero)(void *) = nullptr);
template<typename T>
constexpr AuMemoryView(T *start, AuUInt length); // WARNING: length != count
// where T = whogivesafuck
template<typename T>
constexpr AuMemoryView(T *start, AuUInt length, AuAUInt32 *pInUseCounter, void *pCallbackHandle = nullptr, void (*pfCallbackOnZero)(void *) = nullptr); // WARNING: length != count
template<typename T>
constexpr AuMemoryView(T *start, AuUInt length, AuAUInt32 *pInUseCounter, const AuSPtr<void> &pRAIIOwner, void *pCallbackHandle = nullptr, void (*pfCallbackOnZero)(void *) = nullptr); // WARNING: length != count
private:
template<typename T>
AuMemoryView(T *start, AuUInt length, const AuMemoryViewControlBlock &copyBlock);
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<typename T = AuUInt8>
constexpr AuUInt ToCount() const;
template<typename T = AuUInt8>
constexpr AuUInt Count() const;
template<typename T>
AuConditional_t<Readonly_b, const T *, T *> Begin() const;
template<typename T>
AuConditional_t<Readonly_b, const T*, 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<false> &write) const;
template<bool bThat = Readonly_b, AU_TEMPLATE_ENABLE_WHEN(!bThat)>
AuUInt CopyFrom(const AuMemoryView<true> &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<AuMemoryView> TryPromoteToSharedView(AuSPtr<void> pParent = {}) const;
/// Creates a shader pointer of the view with an optional parent
/// If *this already contains a shared parent, will return nullptr
AuSPtr<AuMemoryView> TryPromoteToSharedViewNoParentNesting(AuSPtr<void> pParent = {}) const;
/// Shares ownership of pCopy, returning false if there is no shared parent.
bool TryDemoteFromSharedView(const AuSPtr<AuMemoryView> &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<AuMemoryView> &pCopy);
/// Interop for other APIs that allow for pinning shared pointers (std::shared_ptr)
AuSPtr<void> 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<true>;
using AuMemoryViewWrite = AuMemoryView<false>;
// 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<bool Readonly_b>
struct AuMemoryViewStream : AuMemoryView<Readonly_b>
{
template<typename T, AU_TEMPLATE_ENABLE_WHEN(AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, T>::value)>
constexpr AuMemoryViewStream(T &list, AuUInt &length) : AuMemoryView<Readonly_b>(list), outVariable(length)
{
outVariable = 0;
}
constexpr AuMemoryViewStream(const AuString &str, AuUInt &length) : AuMemoryView<Readonly_b>(str), outVariable(length)
{
outVariable = 0;
}
template<typename T>
constexpr AuMemoryViewStream(T *start, T *end, AuUInt &length) : AuMemoryView<Readonly_b>(start, end), outVariable(length)
{
outVariable = 0;
}
template<typename T>
constexpr AuMemoryViewStream(T *start, AuUInt &length) : AuMemoryView<Readonly_b>(start, length), outVariable(length)
{
outVariable = 0;
}
template<typename T, int Z>
constexpr AuMemoryViewStream(AuArray<T, Z> &view,
AuUInt &length) :
AuMemoryView<Readonly_b>(view),
outVariable(length)
{
outVariable = 0;
}
template<typename T, typename AuEnableIf<AuIsBaseOfTemplate<AURORA_RUNTIME_AU_LIST, T>::value>::type* = nullptr>
constexpr AuMemoryViewStream(T &list) : AuMemoryView<Readonly_b>(list), outVariable(unused)
{
outVariable = 0;
}
constexpr AuMemoryViewStream(const AuString &str) :
AuMemoryView<Readonly_b>(str),
outVariable(unused)
{
outVariable = 0;
}
constexpr AuMemoryViewStream(const AuROString &str) :
AuMemoryView<Readonly_b>(str),
outVariable(unused)
{
outVariable = 0;
}
constexpr AuMemoryViewStream(const AuRONString &str) :
AuMemoryView<Readonly_b>(str),
outVariable(unused)
{
outVariable = 0;
}
template<typename T>
constexpr AuMemoryViewStream(T *start, T *end) : AuMemoryView<Readonly_b>(start, end), outVariable(unused)
{
outVariable = 0;
}
constexpr AuMemoryViewStream(AuMemoryView<Readonly_b> in) : AuMemoryView<Readonly_b>(in.ptr, in.length), outVariable(unused)
{
outVariable = 0;
}
constexpr AuMemoryViewStream(AuMemoryView<Readonly_b> in, AuUInt &len) : AuMemoryView<Readonly_b>(in.ptr, in.length), outVariable(len)
{
outVariable = 0;
}
template<typename T, int Z>
constexpr AuMemoryViewStream(T(&a)[Z]) : AuMemoryView<Readonly_b>(a), outVariable(unused)
{
outVariable = 0;
}
constexpr bool HasMemory() const
{
return this->ptr && this->length;
}
constexpr operator bool() const
{
return HasMemory();
}
void CopyStreamInto(const AuMemoryView<false> &write) const
{
auto uLength = AuMin(this->uLength, write.uLength);
AuMemcpy(write.pBase, this->pBase, uLength);
this->outVariable = uLength;
}
template<bool bThat = Readonly_b, AU_TEMPLATE_ENABLE_WHEN(!bThat)>
void CopyStreamFrom(const AuMemoryView<true> &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<true>;
using AuMemoryViewStreamWrite = AuMemoryViewStream<false>;

View File

@ -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<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::AuMemoryView()
{
this->ptr = nullptr;
this->length = 0;
}
template<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::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<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::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<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::AuMemoryView(const AuString &str)
{
this->ptr = str.data();
this->length = str.size();
}
template<bool Readonly_b>
AuMemoryView<Readonly_b>::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<bool Readonly_b>
AuMemoryView<Readonly_b>::AuMemoryView(const AuMemoryView &view,
const AuSPtr<void> &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<AuSPtr<void>>(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<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::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<bool Readonly_b>
template<typename T, int Z>
constexpr AuMemoryView<Readonly_b>::AuMemoryView(T(&a)[Z])
{
this->ptr = &a[0];
this->length = Z * sizeof(T);
}
template<bool Readonly_b>
template<typename T, int Z>
constexpr AuMemoryView<Readonly_b>::AuMemoryView(AuArray<T, Z> &view)
{
this->ptr = view.begin();
this->length = Z * sizeof(T);
}
template<bool Readonly_b>
template<typename T>
constexpr AuMemoryView<Readonly_b>::AuMemoryView(T *start, T *end)
{
this->ptr = start;
if constexpr (AuIsSame_v<T, Void_t>)
{
this->length = reinterpret_cast<const AuUInt8 *>(end) - reinterpret_cast<const AuUInt8 *>(start);
}
else
{
this->length = (end - start) * sizeof(T);
}
}
template<bool Readonly_b>
template<typename T>
constexpr AuMemoryView<Readonly_b>::AuMemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, void *pCallbackHandle, void (*pfCallbackOnZero)(void *))
{
this->ptr = start;
if constexpr (AuIsSame_v<T, Void_t>)
{
this->length = reinterpret_cast<const AuUInt8 *>(end) - reinterpret_cast<const AuUInt8 *>(start);
}
else
{
this->length = (end - start) * sizeof(T);
}
this->controlBlock.pInUseCounter = pInUseCounter;
AuAtomicAdd(pInUseCounter, 1u);
this->controlBlock.pCallbackHandle = pCallbackHandle;
this->controlBlock.pfCallbackOnZero = pfCallbackOnZero;
}
template<bool Readonly_b>
template<typename T>
constexpr AuMemoryView<Readonly_b>::AuMemoryView(T *start, T *end, AuAUInt32 *pInUseCounter, const AuSPtr<void> &pRAIIOwner, void *pCallbackHandle, void (*pfCallbackOnZero)(void *))
{
this->ptr = start;
if constexpr (AuIsSame_v<T, Void_t>)
{
this->length = reinterpret_cast<const AuUInt8 *>(end) - reinterpret_cast<const AuUInt8 *>(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<bool Readonly_b>
template<typename T>
constexpr AuMemoryView<Readonly_b>::AuMemoryView(T *start, AuUInt length) // WARNING: length != count
// where T = whogivesafuck
{
this->ptr = start;
this->length = length;
}
template<bool Readonly_b>
template<typename T>
constexpr AuMemoryView<Readonly_b>::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<bool Readonly_b>
template<typename T>
constexpr AuMemoryView<Readonly_b>::AuMemoryView(T *start, AuUInt length, AuAUInt32 *pInUseCounter, const AuSPtr<void> &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<bool Readonly_b>
template<typename T>
AuMemoryView<Readonly_b>::AuMemoryView(T *start, AuUInt length, const AuMemoryViewControlBlock &copyBlock)
{
this->ptr = start;
this->length = length;
this->controlBlock = copyBlock;
if (this->controlBlock.pInUseCounter)
{
AuAtomicAdd(this->controlBlock.pInUseCounter, 1u);
}
}
template<bool Readonly_b>
AuMemoryView<Readonly_b> &AuMemoryView<Readonly_b>::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<bool Readonly_b>
AuMemoryView<Readonly_b> &AuMemoryView<Readonly_b>::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<bool Readonly_b>
constexpr AuUInt AuMemoryView<Readonly_b>::ToPointerValue() const
{
return this->uPtr;
}
template<bool Readonly_b>
constexpr AuUInt AuMemoryView<Readonly_b>::ToLength() const
{
return this->length;
}
template<bool Readonly_b>
constexpr AuUInt AuMemoryView<Readonly_b>::Length() const
{
return this->length;
}
template<bool Readonly_b>
constexpr AuUInt AuMemoryView<Readonly_b>::ToSize() const
{
return this->length;
}
template<bool Readonly_b>
constexpr AuUInt AuMemoryView<Readonly_b>::Size() const
{
return this->length;
}
template<bool Readonly_b>
template<typename T>
constexpr AuUInt AuMemoryView<Readonly_b>::ToCount() const
{
return this->length / sizeof(T);
}
template<bool Readonly_b>
template<typename T>
constexpr AuUInt AuMemoryView<Readonly_b>::Count() const
{
return this->length / sizeof(T);
}
template<bool Readonly_b>
template<typename T>
AuConditional_t<Readonly_b, const T *, T *> AuMemoryView<Readonly_b>::Begin() const
{
return reinterpret_cast<AuConditional_t<Readonly_b, const T *, T *>>(ptr);
}
template<bool Readonly_b>
template<typename T>
AuConditional_t<Readonly_b, const T*, T*> AuMemoryView<Readonly_b>::End() const
{
return Begin<T>() + ToCount<T>();
}
template<bool Readonly_b>
constexpr bool AuMemoryView<Readonly_b>::HasMemory() const
{
return this->ptr && this->length;
}
template<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::operator bool() const
{
return this->HasMemory();
}
template<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::U8_t AuMemoryView<Readonly_b>::ToPointer() const
{
return this->ptrU8;
}
template<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::U8_t AuMemoryView<Readonly_b>::begin() const
{
return this->ptrU8;
}
template<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::U8_t AuMemoryView<Readonly_b>::end() const
{
return this->ptrU8 + this->length;
}
template<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::U8_t AuMemoryView<Readonly_b>::Begin() const
{
return this->ptrU8;
}
template<bool Readonly_b>
constexpr AuMemoryView<Readonly_b>::U8_t AuMemoryView<Readonly_b>::End() const
{
return this->ptrU8 + this->length;
}
template<bool Readonly_b>
constexpr AuUInt AuMemoryView<Readonly_b>::size() const
{
return this->length;
}
template<bool Readonly_b>
AuMemoryView<Readonly_b> AuMemoryView<Readonly_b>::AtOffset(AuUInt uOffset) const
{
if (uOffset < this->uLength)
{
return AuMemoryView((AuUInt8 *)this->pBase + uOffset,
this->uLength - uOffset,
this->controlBlock);
}
else
{
return {};
}
}
template<bool Readonly_b>
AuMemoryView<Readonly_b> AuMemoryView<Readonly_b>::Take(AuUInt uLength) const
{
if (uLength <= this->uLength)
{
return AuMemoryView((AuUInt8 *)this->pBase,
uLength,
this->controlBlock);
}
else
{
return {};
}
}
template<bool Readonly_b>
AuMemoryView<Readonly_b> AuMemoryView<Readonly_b>::Clone() const
{
auto uLength = this->uLength;
auto pData = AuMakeSharedArray<AuUInt8>(uLength);
if (!pData)
{
return {};
}
AuMemcpy(pData.get(), this->pBase, uLength);
return AuMemoryView(AuMemoryView(pData.get(), uLength), pData);
}
template<bool Readonly_b>
AuMemoryView<Readonly_b> AuMemoryView<Readonly_b>::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 Readonly_b>
bool AuMemoryView<Readonly_b>::TryCloneSelf(bool bResetOnFailure)
{
auto replacement = Clone();
if (!replacement)
{
if (bResetOnFailure)
{
AuResetMember(*this);
}
return false;
}
AuResetMember(*this, replacement);
return true;
}
template<bool Readonly_b>
bool AuMemoryView<Readonly_b>::HasControlBlock() const
{
return this->controlBlock.pInUseCounter ||
this->controlBlock.pPinner ||
this->controlBlock.pfCallbackOnZero;
}
template<bool Readonly_b>
AuSPtr<AuMemoryView<Readonly_b>> AuMemoryView<Readonly_b>::TryPromoteToSharedView(AuSPtr<void> pParent) const
{
#if 0
bool bHasControlBlock = this->HasControlBlock();
if (bHasControlBlock)
{
if (pParent)
{
return AuMakeShared<AuMemoryView>(*this, pParent);
}
else
{
return AuMakeShared<AuMemoryView>(*this);
}
}
else
{
if (pParent)
{
return AuMakeShared<AuMemoryView>(*this, pParent);
}
else
{
return {};
}
}
#else
if (pParent)
{
return AuMakeShared<AuMemoryView>(*this, pParent);
}
if (this->HasControlBlock())
{
return AuMakeShared<AuMemoryView>(*this);
}
return {};
#endif
}
template<bool Readonly_b>
AuSPtr<AuMemoryView<Readonly_b>> AuMemoryView<Readonly_b>::TryPromoteToSharedViewNoParentNesting(AuSPtr<void> pParent) const
{
if (this->HasControlBlock())
{
return AuMakeShared<AuMemoryView>(*this);
}
if (pParent)
{
return AuMakeShared<AuMemoryView>(*this, pParent);
}
return {};
}
template<bool Readonly_b>
bool AuMemoryView<Readonly_b>::TryDemoteFromSharedView(const AuSPtr<AuMemoryView<Readonly_b>> &pCopy)
{
if (pCopy && pCopy->HasControlBlock())
{
AuResetMember(*this, AuConstReference(*pCopy.get()));
return true;
}
else
{
return false;
}
}
template<bool Readonly_b>
bool AuMemoryView<Readonly_b>::TryDemoteFromReference(const AuMemoryView &refCopy)
{
if (refCopy.HasControlBlock())
{
AuResetMember(*this, refCopy);
return true;
}
else
{
return false;
}
}
template<bool Readonly_b>
void AuMemoryView<Readonly_b>::DemoteFromSharedView(const AuSPtr<AuMemoryView<Readonly_b>> &pCopy)
{
if (!pCopy)
{
AuResetMember(*this);
return;
}
if (pCopy->HasControlBlock())
{
AuResetMember(*this, AuConstReference(*pCopy.get()));
}
else
{
AuResetMember(*this, AuConstReference(*pCopy.get()), pCopy);
}
}
template<bool Readonly_b>
AuSPtr<void> AuMemoryView<Readonly_b>::ToSharedControlBlock(bool *pbFailed)
{
if (pbFailed)
{
*pbFailed = false;
}
if (this->controlBlock.pInUseCounter)
{
auto pShared = AuMakeShared<AuMemoryViewControlBlock>();
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<bool Readonly_b>
AuUInt AuMemoryView<Readonly_b>::CopyInto(const AuMemoryView<false> &write) const
{
auto uLength = AuMin(this->uLength, write.uLength);
AuMemcpy(write.pBase, this->pBase, uLength);
return uLength;
}

View File

@ -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 <class T>
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 <class Z>
struct rebind
{
using other = AuPMRAllocator<Z>;
};
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<AuHeap> pHeap) :
#if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER)
spHeap(pHeap),
pHeap(pHeap.get())
#else
spHeap(pHeap)
#endif
{ }
inline AuPMRAllocator(AuHeap *pHeap, AuSSPtr<void> pThat = {}) :
#if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER)
spHeap(pThat),
pHeap(pHeap)
#else
spHeap(AuSharedPointerFromShared(pHeap, pThat))
#endif
{ }
template <class B>
inline AuPMRAllocator(const AuPMRAllocator<B> &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<T *> allocate_at_least(const size_t count)
{
auto pThat = this->allocate(count);
return { (T *)pThat, this->GetHeapRaw()->GetChunkSize(pThat) / sizeof(T) };
}
#endif
template <class U, class... Args >
void construct(U *p, Args&&... args)
{
new ((void *)p) U(AuForward<Args>(args)...);
}
template <class U, class... Args >
void construct_at(U *p, Args&&... args)
{
new ((void *)p) U(AuForward<Args>(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 <class U>
U *allocate_object(std::size_t n = 1)
{
return (U *)this->allocate_bytes(sizeof(U) * n, alignof(U));
}
template <class U>
void deallocate_object(U *p, std::size_t n = 1)
{
this->deallocate_bytes(p, 0, 0);
}
template <class U, class... CtorArgs>
U *new_object(CtorArgs&&... args)
{
U *p = this->allocate_object<U>();
try
{
this->construct(p, AuForward<CtorArgs>(args)...);
}
catch (...)
{
this->deallocate_object(p);
throw;
}
return p;
}
template <class U>
void delete_object(U *p)
{
if constexpr (AuIsClass_v<U> &&
!AuIsTriviallyDestructible_v<U>)
{
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<AuHeap> 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 <class Z>
bool operator==(const AuPMRAllocator<Z> &rhs) noexcept
{
return this->GetHeapRaw() == rhs.GetHeapRaw();
}
template <class Z>
bool operator!=(const AuPMRAllocator<Z> &rhs) noexcept
{
return this->GetHeapRaw() == rhs.GetHeapRaw();
}
private:
#if defined(AU_NO_COMPRESS_CPPHEAP_WRAPPER)
mutable AuSSPtr<void> spHeap;
mutable AuHeap *pHeap {};
#else
mutable AuSSPtr<AuHeap> spHeap;
#endif
template <typename Z>
friend struct AuPMRAllocator;
};
template <class T, class Z>
inline bool operator==(const AuPMRAllocator<T> &lhs,
const AuPMRAllocator<Z> &rhs) noexcept
{
return lhs.GetHeapRaw() == rhs.GetHeapRaw();
}
template <class T, class Z>
inline bool operator!=(const AuPMRAllocator<T> &lhs,
const AuPMRAllocator<Z> &rhs) noexcept
{
return lhs.GetHeapRaw() != rhs.GetHeapRaw();
}

View File

@ -7,14 +7,8 @@
***/
#pragma once
namespace Aurora::Memory
{
struct Heap;
}
template <typename T>
bool AuSetAllocator(T &that, AuHeap *pHeap);
template <typename T>
static bool AuSetAllocator(T &that, Aurora::Memory::Heap *pHeap);
template <typename T>
static bool AuSetAllocator(T &that, const AuSPtr<Aurora::Memory::Heap> &pHeap);
bool AuSetAllocator(T &that, const AuSPtr<AuHeap> &pHeap);

View File

@ -12,7 +12,7 @@ namespace __audetail
template <class T>
struct AuHasSetAllocatorRawVoid
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(Aurora::Memory::Heap *)>(&C::SetAllocator)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(AuHeap *)>(&C::SetAllocator)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
@ -20,14 +20,14 @@ namespace __audetail
template <class T>
struct AuHasSetAllocatorRawBool
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(Aurora::Memory::Heap *)>(&C::SetAllocator)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(AuHeap *)>(&C::SetAllocator)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
template <class T>
struct AuHasSetHeapRawVoid
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(Aurora::Memory::Heap *)>(&C::SetHeap)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(AuHeap *)>(&C::SetHeap)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
@ -35,15 +35,15 @@ namespace __audetail
template <class T>
struct AuHasSetHeapRawBool
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(Aurora::Memory::Heap *)>(&C::SetHeap)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(AuHeap *)>(&C::SetHeap)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
template <class T>
struct AuHasSetAllocatorSVoid
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(AuSPtr<Aurora::Memory::Heap>)>(&C::SetAllocator)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(const AuSPtr<Aurora::Memory::Heap> &)>(&C::SetAllocator)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(AuSPtr<AuHeap>)>(&C::SetAllocator)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(const AuSPtr<AuHeap> &)>(&C::SetAllocator)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
@ -51,8 +51,8 @@ namespace __audetail
template <class T>
struct AuHasSetAllocatorSBool
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(AuSPtr<Aurora::Memory::Heap>)>(&C::SetAllocator)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(const AuSPtr<Aurora::Memory::Heap> &)>(&C::SetAllocator)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(AuSPtr<AuHeap>)>(&C::SetAllocator)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(const AuSPtr<AuHeap> &)>(&C::SetAllocator)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
@ -60,8 +60,8 @@ namespace __audetail
template <class T>
struct AuHasSetHeapSVoid
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(AuSPtr<Aurora::Memory::Heap>)>(&C::SetHeap)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(const AuSPtr<Aurora::Memory::Heap> &)>(&C::SetHeap)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(AuSPtr<AuHeap>)>(&C::SetHeap)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(const AuSPtr<AuHeap> &)>(&C::SetHeap)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
@ -69,8 +69,8 @@ namespace __audetail
template <class T>
struct AuHasSetHeapSBool
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(AuSPtr<Aurora::Memory::Heap>)>(&C::SetHeap)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(const AuSPtr<Aurora::Memory::Heap> &)>(&C::SetHeap)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(AuSPtr<AuHeap>)>(&C::SetHeap)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(const AuSPtr<AuHeap> &)>(&C::SetHeap)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
@ -78,8 +78,8 @@ namespace __audetail
template <class T>
struct AuHasSetHeapSharedSVoid
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(AuSPtr<Aurora::Memory::Heap>)>(&C::SetHeapShared)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(const AuSPtr<Aurora::Memory::Heap> &)>(&C::SetHeapShared)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(AuSPtr<AuHeap>)>(&C::SetHeapShared)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<void (C:: *)(const AuSPtr<AuHeap> &)>(&C::SetHeapShared)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
@ -87,8 +87,8 @@ namespace __audetail
template <class T>
struct AuHasSetHeapSharedSBool
{
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(AuSPtr<Aurora::Memory::Heap>)>(&C::SetHeapShared)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(const AuSPtr<Aurora::Memory::Heap> &)>(&C::SetHeapShared)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(AuSPtr<AuHeap>)>(&C::SetHeapShared)));
template <class C> static constexpr AuTrueType Test(decltype(static_cast<bool (C:: *)(const AuSPtr<AuHeap> &)>(&C::SetHeapShared)));
template <class C> static constexpr AuFalseType Test(...);
using type = decltype(Test<T>(0));
};
@ -136,7 +136,7 @@ namespace __audetail
}
template <typename T>
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 <typename T>
static bool AuSetAllocator(T &that, const AuSPtr<Aurora::Memory::Heap> &pHeap)
bool AuSetAllocator(T &that, const AuSPtr<AuHeap> &pHeap)
{
if (!pHeap)
{

View File

@ -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 <typename T, typename Deleter_t = void(*)(T *)>
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 <typename U>
AuUniquePointer(AuUniquePointer<U> &&that);
~AuUniquePointer();
AuUniquePointer &operator=(std::nullptr_t);
template <typename U>
AuUniquePointer &operator=(AuUniquePointer<U> &&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 <typename T, typename Deleter_t>
void Swap(AuUniquePointer<T, Deleter_t> &lhs, AuUniquePointer<T, Deleter_t> &rhs)
{
lhs.swap(rhs);
}
namespace std
{
template <typename T, typename Deleter_t>
void swap(AuUniquePointer<T, Deleter_t> &lhs, AuUniquePointer<T, Deleter_t> &rhs)
{
lhs.swap(rhs);
}
}

View File

@ -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 <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t>::AuUniquePointer()
{}
template <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t>::AuUniquePointer(std::nullptr_t)
{}
template <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t>::AuUniquePointer(T *pThat) :
pThat(pThat)
{}
template <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t>::AuUniquePointer(T *pThat, const Deleter_t &deleter) :
pThat(pThat),
deleter(deleter)
{}
template <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t>::AuUniquePointer(T *pThat, Deleter_t &&deleter) :
pThat(pThat),
deleter(AuMove(deleter))
{}
template <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t>::AuUniquePointer(AuUniquePointer &&that) noexcept
{
that.Swap(*this);
}
template <typename T, typename Deleter_t>
template <typename U>
AuUniquePointer<T, Deleter_t>::AuUniquePointer(AuUniquePointer<U> &&that)
{
AuUniquePointer<T> temp(that.Release(), that.GetDeleter());
temp.Swap(*this);
}
template <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t>::~AuUniquePointer()
{
if (!this->pThat)
{
return;
}
if constexpr (AuIsFunction_v<Deleter_t>)
{
if (this->deleter)
{
this->deleter(this->pThat);
}
else
{
AuDefaultDeleter<T>()(this->pThat);
}
}
else
{
this->deleter(this->pThat);
}
}
template <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t> &AuUniquePointer<T, Deleter_t>::operator=(std::nullptr_t)
{
this->Reset();
return *this;
}
template <typename T, typename Deleter_t>
template <typename U>
AuUniquePointer<T, Deleter_t> &AuUniquePointer<T, Deleter_t>::operator=(AuUniquePointer<U> &&that) noexcept
{
AuUniquePointer<T> temp(that.Release(), that.GetDeleter());
temp.Swap(*this);
return *this;
}
template <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t> &AuUniquePointer<T, Deleter_t>::operator=(AuUniquePointer<T, Deleter_t> &&that) noexcept
{
that.Swap(*this);
return *this;
}
template <typename T, typename Deleter_t>
T *AuUniquePointer<T, Deleter_t>::operator->() const
{
return this->pThat;
}
template <typename T, typename Deleter_t>
T &AuUniquePointer<T, Deleter_t>::operator*() const
{
return *this->pThat;
}
template <typename T, typename Deleter_t>
T *AuUniquePointer<T, Deleter_t>::get() const
{
return this->pThat;
}
template <typename T, typename Deleter_t>
AuUniquePointer<T, Deleter_t>::operator bool() const
{
return this->pThat;
}
template <typename T, typename Deleter_t>
T *AuUniquePointer<T, Deleter_t>::Release() noexcept
{
T *pRet {};
AuSwap(pRet, this->pThat);
return pRet;
}
template <typename T, typename Deleter_t>
T *AuUniquePointer<T, Deleter_t>::release() noexcept
{
return this->Release();
}
template <typename T, typename Deleter_t>
void AuUniquePointer<T, Deleter_t>::Swap(AuUniquePointer &that) noexcept
{
AuSwap(this->pThat, that.pThat);
AuSwap(this->deleter, that.deleter);
}
template <typename T, typename Deleter_t>
void AuUniquePointer<T, Deleter_t>::swap(AuUniquePointer &that) noexcept
{
this->Swap(that);
}
template <typename T, typename Deleter_t>
void AuUniquePointer<T, Deleter_t>::Reset()
{
if (auto pThat = Release())
{
if constexpr (AuIsFunction_v<Deleter_t>)
{
if (this->deleter)
{
this->deleter(pThat);
}
else
{
AuDefaultDeleter<T>()(pThat);
}
}
else
{
this->deleter(pThat);
}
}
}
template <typename T, typename Deleter_t>
void AuUniquePointer<T, Deleter_t>::reset()
{
this->Reset();
}
template <typename T, typename Deleter_t>
const Deleter_t &AuUniquePointer<T, Deleter_t>::GetDeleter() const noexcept
{
return this->deleter;
}
template <typename T, typename Deleter_t>
const Deleter_t &AuUniquePointer<T, Deleter_t>::get_deleter() const noexcept
{
return this->GetDeleter();
}

View File

@ -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 <class ... T> \
extends ## Unique_t Type ## UniqueOnHeap(AuHeap *pHeap, T &&... args) \
{ \
return pHeap->NewClassUnique<Type>(AuForward<T>(args)...); \
} \
\
template <class ... T> \
extends ## Shared_t Type ## SharedOnHeap(AuHeap *pHeap, T &&... args) \
{ \
return pHeap->NewClass<Type>(AuForward<T>(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))) \

View File

@ -141,15 +141,33 @@ namespace Aurora::Memory
#endif
}
template < class Y, class Deleter >
ExSharedPtr(AURORA_RUNTIME_AU_UNIQUE_PTR<Y, Deleter> &&r) : Base_t(AuMove(r))
template <class Y, class Deleter>
ExSharedPtr(AURORA_RUNTIME_AU_UNIQUE_PTR<Y, Deleter> &&r)
{
if constexpr (AuIsFunction_v<Deleter>)
{
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 <class T_t, typename B_t>
void swap(ExSharedPtr<T_t, B_t> &in)
{

View File

@ -17,7 +17,7 @@ template <class T, typename Z, typename LessThan_t = AuHash::less<T>, class Allo
using AuBST = AURORA_RUNTIME_AU_BST<T, Z, LessThan_t, Allocator_t>;
template <class T, typename Z, typename LessThan_t = AuHash::less<T>>
using AuBSTOfHeap = AuBST<T, Z, LessThan_t, Aurora::Memory::PmrCppHeapWrapper<AuPair<const T, Z>>>;
using AuBSTOfHeap = AuBST<T, Z, LessThan_t, AuPMRAllocator<AuPair<const T, Z>>>;
template<typename T>
struct AuIsBST : AuFalseType

View File

@ -17,7 +17,7 @@ template <class T, class Z, class Hash_t = AuHash::hash<T>, class Equal_t = AuHa
using AuHashMap = AURORA_RUNTIME_AU_HASH_MAP<T, Z, Hash_t, Equal_t, Allocator_t>;
template <class T, class Z, class Hash_t = AuHash::hash<T>, class Equal_t = AuHash::equal<T>>
using AuHashMapOfHeap = AuHashMap<T, Z, Hash_t, Equal_t, Aurora::Memory::PmrCppHeapWrapper<AuPair<const T, Z>>>;
using AuHashMapOfHeap = AuHashMap<T, Z, Hash_t, Equal_t, AuPMRAllocator<AuPair<const T, Z>>>;
template<typename T>
struct AuIsHashMap : AuFalseType

View File

@ -26,4 +26,4 @@
#endif
template <class T>
using AuListOfHeap = AuList<T, Aurora::Memory::PmrCppHeapWrapper<T>>;
using AuListOfHeap = AuList<T, AuPMRAllocator<T>>;

View File

@ -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 <class T>
using AuWPtr = AURORA_RUNTIME_AU_WEAK_PTR<T>;
#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 <auROXTL/MemoryModel/auUniquePointer.hpp>
#include "STLShims/ExtendStlLikeSharedPtr.hpp"
template <class T>
using AuSPtr = typename Aurora::Memory::ExSharedPtr<T, AURORA_RUNTIME_AU_SHARED_PTR<T>>;
template <class T, typename Deleter_t>
template <class T>
using AuSSPtr = typename AURORA_RUNTIME_AU_SHARED_PTR<T>;
template <class T, typename Deleter_t = void(*)(T *)>
using AuUPtr = AURORA_RUNTIME_AU_UNIQUE_PTR<T, Deleter_t>;
#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 <class T>
struct AuPMRAllocator;
namespace Aurora::Memory
{
template <class T>
struct CppHeapWrapper;
template <class T>
struct PmrCppHeapWrapper;
#if defined(AURORA_ROXTL_ALLOCATORS_USE_STD)
@ -306,31 +323,7 @@ namespace Aurora::Memory
#endif
template <class T, typename... Args>
static auline AuSPtr<T> AuMakeShared(Args&&... args)
{
using Z = AuRemoveConst_t<T>;
try
{
#if defined(AURORA_ROXTL_ALLOCATORS_USE_STD)
return AURORA_RUNTIME_MAKE_SHARED<T>(AuForward<Args>(args)...);
#else
auto pNext = Aurora::Memory::__FAlloc(sizeof(T), alignof(T));
if (!pNext)
{
return nullptr;
}
auto pNextClass = (Z *)pNext;
new (pNextClass) Z (AuForward<Args>(args)...);
return std::shared_ptr<T>(pNextClass, Aurora::Memory::DefaultRuntimeDeleter<Z> {}, Aurora::Memory::SharedControlBlockAllocator<T> {});
#endif
}
catch (...)
{
return {};
}
}
AuSPtr<T> AuMakeShared(Args&&... args);
template <class T, typename... Args>
static auline AuSPtr<T> AuMakeSharedPanic(Args&&... args)
@ -418,17 +411,18 @@ namespace __audetail
char a;
};
inline AuSPtr<Dummy> gDummy;
inline AuSPtr<Dummy> GetDummyDeleter()
{
static AuSPtr<Dummy> d;
if (!d)
if (!gDummy)
{
#if defined(AURORA_COMPILER_MSVC)
return d;
return gDummy;
#endif
d = AuMakeShared<Dummy>();
gDummy = AuMakeShared<Dummy>();
}
return d;
return gDummy;
}
}
@ -459,3 +453,13 @@ inline constexpr bool operator!=(const Aurora::Memory::BaseAuroraRuntimeAllocato
}
#include <auROXTL/MemoryModel/auSetAllocator.hpp>
#include <auROXTL/MemoryModel/auPMRAllocator.hpp>
#include <auROXTL/MemoryModel/auHeapStats.hpp>
#include <auROXTL/MemoryModel/auHeap.hpp>
#include <auROXTL/MemoryModel/auHeapAccessor.hpp>
#include <auROXTL/MemoryModel/auDummyHeap.hpp>
#include <auROXTL/MemoryModel/auMemoryAllocate.hpp>

View File

@ -169,6 +169,8 @@ namespace __audetail
#include <auROXTL/auVector.hpp>
#include <auROXTL/auArray.hpp>
#include <auROXTL/auArrayList.hpp>
#include <auROXTL/auAtomic.hpp>
#include <auROXTL/MemoryModel/auMemoryView.hpp>
#include <auROXTL/auOptional.hpp>
#include <auROXTL/auOptionalEx.hpp>
#include <auROXTL/Iterators/auUTF8Iterator.hpp>

View File

@ -78,6 +78,10 @@ namespace __audetail
#include <auROXTL/MemoryModel/auSetAllocator.ipp>
#include <auROXTL/MemoryModel/auHeap.ipp>
#include <auROXTL/MemoryModel/auUniquePointer.ipp>
#include <auROXTL/MemoryModel/auMemoryView.ipp>
struct IAuNullDelegate
{
virtual void OnCall() = 0;