diff --git a/Include/auROXTL/AU_MACROS.hpp b/Include/auROXTL/AU_MACROS.hpp index e8f0b43..0b02d04 100644 --- a/Include/auROXTL/AU_MACROS.hpp +++ b/Include/auROXTL/AU_MACROS.hpp @@ -69,11 +69,19 @@ } \ }; \ \ - using name ## Unique_t = AuUPtr; \ + using name ## SmallUnique_t = AuUPtr; \ + using name ## SUnique_t = AuUPtr; \ + using name ## Unique_t = name ## SmallUnique_t; \ + using name ## GUnique_t = AuHUPOf_t; \ template \ - name ## Unique_t name ## Unique(T &&... args) \ + name ## GUnique_t name ## GenericUnique(T &&... args) \ { \ - return name ## Unique_t(name ## New(AuForward(args)...), name ## Release); \ + return name ## GUnique_t(name ## New(AuForward(args)...), name ## Release); \ + } \ + template \ + name ## SmallUnique_t name ## Unique(T &&... args) \ + { \ + return name ## SmallUnique_t(name ## New(AuForward(args)...)); \ } \ \ using name ## Shared_t = AuSPtr; \ @@ -290,4 +298,14 @@ struct AuStringOwnedException : AuStringException #include "Objects/Objects.hpp" -#include "AU_USING.hpp" \ No newline at end of file +#include "AU_USING.hpp" + +#if defined(AURORA_ROXTL_HAS_DELETER_ASSERT) +#define _AUROXTL_DELETER_ASSERT(pThat, Type) \ + if (pThat.GetDeleter() != Type::Get()) \ + { \ + AuMemoryPanic("Invalid Deleter"); \ + } +#else +#define _AUROXTL_DELETER_ASSERT(pThat, Type) +#endif \ No newline at end of file diff --git a/Include/auROXTL/MemoryModel/auMemoryAllocate.hpp b/Include/auROXTL/MemoryModel/auMemoryAllocate.hpp index 34948bd..9acd438 100755 --- a/Include/auROXTL/MemoryModel/auMemoryAllocate.hpp +++ b/Include/auROXTL/MemoryModel/auMemoryAllocate.hpp @@ -8,6 +8,91 @@ ***/ #pragma once +// +// AuHUPOf_t AuNewClassArrayUnique([pHeap, ]uElements, ...) +// AuUPtr AuNewClassArrayUnique([pHeap, ]uElements, ...) [ 2024/09 ] +// AuSPtr AuNewClassArray([pHeap, ]uElements, ...) +// AuHUPOf_t AuNewClassUnique([pHeap, ] ...) +// AuUPtr AuNewClassUnique([pHeap, ] ...) +// sizeof( AuHUPOf_t ) == +// sizeof( AuUPtr ) == [ 2024/09 ] +// 2 * sizeof( void * ) +// AuHPtr AuNewClassSmallUnique([pHeap, ] ...) [ 2024/09 ] +// sizeof( AuHPtr ) == sizeof( void * ) +// AuSPtr AuNewClass([pHeap, ] ...) +// sizeof(AuSPtr) ~= 2x (void *) +// AuHUPOf_t AuNullHeapPointer() +// AuUPtr AuNullHeapPointer() [ 2024/09 ] +// AuSPtr AuMakeShared(...) +// +// AuSPtr - shared +// +// AuSSPtr - shared (special. if the shared pointer container is too big, this type may shrink it down. ) +// (this maybe useful for storing parent pointers in foreign places or small slots. ) +// +// AuHPtr - unique with immutable instantiated deleter (...) of derived main class (= T) +// +// AuHUPOf_t - unique of a function callback; relevant prior to 2024/09. +// - could be assigned to null with AuNullHeapPointer; relevant prior to 2024/09. +// - use me instead of AuUPtr to be compatible to pre 2024/09 codebases. +// +// AuUPtr - close to what youd expect from a std::unique_pointer with special edge cases. +// +// AuUPtr - prior to 2024/09, invalid +// AuUPtr - after 2024/09, an empty function callback unique pointer container. 2x void* +// - use me for maximum laziness +// after 2024/09: +// std::shared_ptr a = { AuSPtr() } +// std::unique_ptr a = { AuUPtr().Release(), AuUPtr().GetDeleter() } +// AuUPtr a = { std::unique_ptr().release(), std::unique_ptr().get_deleter() } +// AuSPtr a = { std::shared_ptr() } +// AuHUPOf_t a = AuNullHeapPointer() (2x void * sized container) +// AuUPtr a = AuNullHeapPointer() (2x void * sized container) +// AuHUPOf_t a { AuMove(AuUPtr) } (2x void * sized container) +// AuUPtr a { AuMove(AuHUPOf_t) } (2x void * sized container) +// AuUPtr a { _new Kot() } (2x void * sized container) +// AuSPtr a { AuMove(a) } (N/A Shared Pointer) +// AuHUPOf_t a { } (2x void * sized container) +// AuUPtr a { } (2x void * sized container) +// AuHUPOf_t a = SomeAPI(...) (2x void * sized container) +// AuUPtr a = SomeAPI(...) (2x void * sized container) +// AuUPtr a = SOOObjectGenericUnique(...) (2x void * sized container) +// AuHUPOf_t a = SOOObjectGenericUniqueOnHeap(pMyHeap, ...) (2x void * sized container) +// AuUPtr a = SOOObjectGenericUniqueOnHeap(pMyHeap, ...) (2x void * sized container) +// AuUPtr|SOOOnHeapUnique_t a = +// SOOObjectUniqueOnHeap(pMyHeap, ...) (void* sized container) +// AuSPtr a = SOOObjectSharedOnHeap(pMyHeap) (N/A Shared Pointer) +// SOOObject...cont as FuncName +// AuUPtr|FuncNameUnique_t a = FuncNameUnique() (void* sized container) +// AuUPtr a = FuncNameGenericUnique() (2x void * sized container) +// AuUPtr|FuncNameSmallUnique_t a = FuncNameUnique() (void* sized container - old behaviour, lower overhead) +// AuHPtr a = FuncNameGenericUnique() (void* sized container - old behaviour, lower overhead) +// AuSPtr a = FuncNameShared() (N/A Shared Pointer) +// AuHPtrs of SmallUnique's are becoming the new AuHUPOf_t() +// before 2024/09: +// std::shared_ptr a = { AuSPtr() } +// AuUPtr a = { std::unique_ptr().release(), std::unique_ptr().get_deleter() } +// AuSPtr a = { std::shared_ptr() } +// AuUPtr> a { _new Kot() } (void * sized container) +// AuHUPOf_t a = AuNullHeapPointer() (2x void * sized container) +// AuSPtr a { AuMove(a) } (N/A Shared Pointer) +// AuHUPOf_t a = pHeap->XXXXUnique(...) (2x void * sized container) +// AuHUPOf_t a = AuNewXXXXUnique(...) (2x void * sized container) +// AuHUPOf_t a = SomeAPI(...) (2x void * sized container) +// AuUPtr a = FuncNameUnique() (void* sized container) +// AuUPtr|FuncNameUnique_t a = FuncNameUnique() (void* sized container) +// AuSPtr a = FuncNameShared() (N/A Shared Pointer) +// AuHPtr - did not exist +// but still: +// AuHUPOf_t will be kept around just in case we need to build against the spec, I suppose. +// +// AuUPtr is a superset of the C++ std::unique_ptr, no matter the era. +// std::unique_ptr must be substitutable with an AuUPtr +// +// (modern) AuHPtr replaces in-library use cases for AuHUPOf_t and AuUPtr. +// ironically enough, we've just reintented a new AuHUPOf_t. +// + #if defined(AURORA_ROXTL_HAS_RUNTIME) && AURORA_ROXTL_HAS_RUNTIME namespace Aurora::Memory { @@ -59,9 +144,26 @@ auline AuSPtr AuMakeShared(Args &&... args) #endif } +// can carry casts +// 2024/09 onward, this is an artifact from when we were using STL unique pointers +// this is now the same as AuUPtr as implemented by . +// beforehand, AuUPtr needed a destructor of a class deallocator with a nonnull constructor (something something nulls are bad mokay we can just design them out). +// In either case, AuHUPOf_t could be cast at least once. +// In either case, the sizeof this is always 2x (void *)-ish. +// In either case, can carry T[] template using AuHUPOf_t = AuUPtr; +// cannot carry casts, is equal to sizeof(void *) +template +using AuHSUPOf_t = AuUPtr>; + +// used for non-api unique allocates, where T = base and derived type, and the container sizeof is only void *. +// cannot carry T[] +// cannot carry derived -> interface casts +template +using AuHPtr = AuHSUPOf_t; + template auto AuNullHeapPointer() { @@ -114,10 +216,10 @@ AuSPtr AuNewClassArray(AuHeap *pHeap, AuUInt uElements, Args &&... fillCtr) return pHeap->NewClassArray(uElements, AuForward(fillCtr)...); } -template -AuHUPOf_t AuNewClassUnique(AuHeap *pHeap, Args &&...args) +template +AuHUPOf_t AuNewClassUnique(AuHeap *pHeap, Args &&...args) { - return pHeap->NewClassUnique(AuForward(args)...); + return pHeap->NewClassUnique(AuForward(args)...); } template @@ -126,6 +228,35 @@ AuSPtr AuNewClass(AuHeap *pHeap, Args &&...args) return pHeap->NewClass(AuForward(args)...); } +template +AuHPtr AuNewClassUniqueSmall(AuHeap *pHeap, Args &&...args) +{ + if (!pHeap) + { + return AuHPtr {}; + } + auto pThat = pHeap->NewClassUnique(AuForward(args)...); + if (!pThat) + { + return AuHPtr {}; + } + auto pMyPointerNow = pThat.Release()->AsPointer(); + _AUROXTL_DELETER_ASSERT(pThat, AuHeapUniqueDeleterClass); + return AuHPtr { pMyPointerNow }; +} + +template +AuHPtr AuNewClassUniqueSmall(const AuSPtr &pHeap, Args &&...args) +{ + return AuNewClassUniqueSmall(pHeap.get(), AuForward(args)...); +} + +template +AuHPtr AuNewClassUniqueSmall(Args &&...args) +{ + return AuNewClassUniqueSmall(__audetail::gDefaultDiscontiguousHeap, AuForward(args)...); +} + template AuHUPOf_t AuNewClassArrayUnique(const AuSPtr &pHeap, AuUInt uElements, Args &&... fillCtr) { diff --git a/Include/auROXTL/Objects/SOO.hpp b/Include/auROXTL/Objects/SOO.hpp index a2a5aa2..dad93d8 100644 --- a/Include/auROXTL/Objects/SOO.hpp +++ b/Include/auROXTL/Objects/SOO.hpp @@ -112,8 +112,13 @@ struct AU_ALIGN(sizeof(AuUInt)) Type ## SOO using Type ## SOO_t = Type ## SOO; \ using Type = Type ## SOO; \ \ + using CppDeleterSOOX ## Type = AuHeapUniqueDeleterClass; \ + using Type ## OnHeapUnique_t = AuUPtr; \ + using Type ## UniqueOnHeap_t = Type ## OnHeapUnique_t; \ + using Type ## GenericUniqueOnHeap_t = AuUPtr; \ + \ template \ - AuUPtr Type ## UniqueOnHeap(AuHeap *pHeap, T &&... args) \ + AuUPtr Type ## GenericUniqueOnHeap(AuHeap *pHeap, T &&... args) \ { \ auto pThat = pHeap->NewClassUnique(AuForward(args)...); \ if (!pThat) \ @@ -127,6 +132,19 @@ using Type = Type ## SOO; } \ \ template \ + Type ## OnHeapUnique_t Type ## UniqueOnHeap(AuHeap *pHeap, T &&... args) \ + { \ + auto pThat = pHeap->NewClassUnique(AuForward(args)...); \ + if (!pThat) \ + { \ + return Type ## OnHeapUnique_t {}; \ + } \ + auto pMyPointerNow = pThat.Release()->AsPointer(); \ + _AUROXTL_DELETER_ASSERT(pThat.GetDeleter(), CppDeleterSOOX ## Type); \ + return Type ## OnHeapUnique_t { pMyPointerNow }; \ + } \ + \ + template \ AuSPtr Type ## SharedOnHeap(AuHeap *pHeap, T &&... args) \ { \ auto pThat = pHeap->NewClass(AuForward(args)...); \