Compare commits

...

2 Commits

Author SHA1 Message Date
a563ba611f [+] AuNewClassSmallUnique
[+] Object API Unique pointers are small again (8 bytes)
[+] Object API GenericUnique to handle the generic AuUPtr<T>
[+] SOO GenericUniqueOnHeap
[+] SOO UniqueOnHeap
[+] AuHPtr<T>
[*] Fixed raw heap pointer variant of AuNewClassUnique<T, missing: Z>
2024-09-22 17:20:16 +01:00
c3a1ae1576 [+] AuHeapUniqueDeleterClass 2024-09-22 17:14:56 +01:00
7 changed files with 214 additions and 9 deletions

View File

@ -69,11 +69,19 @@
} \
}; \
\
using name ## Unique_t = AuUPtr<type>; \
using name ## SmallUnique_t = AuUPtr<type, CppDeleter ## name>; \
using name ## SUnique_t = AuUPtr<type, CppDeleter ## name>; \
using name ## Unique_t = name ## SmallUnique_t; \
using name ## GUnique_t = AuHUPOf_t<type>; \
template <class ... T> \
name ## Unique_t name ## Unique(T &&... args) \
name ## GUnique_t name ## GenericUnique(T &&... args) \
{ \
return name ## Unique_t(name ## New(AuForward<T &&>(args)...), name ## Release); \
return name ## GUnique_t(name ## New(AuForward<T &&>(args)...), name ## Release); \
} \
template <class ... T> \
name ## SmallUnique_t name ## Unique(T &&... args) \
{ \
return name ## SmallUnique_t(name ## New(AuForward<T &&>(args)...)); \
} \
\
using name ## Shared_t = AuSPtr<type>; \
@ -290,4 +298,14 @@ struct AuStringOwnedException : AuStringException
#include "Objects/Objects.hpp"
#include "AU_USING.hpp"
#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

View File

@ -0,0 +1,26 @@
/***
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuHeapUniqueDeleterClass.hpp
Date: 2024-09-22
Author: Reece
***/
#pragma once
template <typename Type, typename Expects = Type>
struct AuHeapUniqueDeleterClass : AuHeapAccessor2
{
inline static auto Get()
{
return AuHeapAccessor2::Get<Type>();
}
inline void operator()(Expects *pThat) const
{
if (!pThat)
{
return;
}
Get()((Type *)pThat);
}
};

View File

@ -141,6 +141,7 @@ public:
protected:
friend struct AuHeapAccessor;
friend struct AuHeapAccessor2;
friend struct Aurora::Memory::ProxyHeap;
virtual AuSPtr<AuHeap> GetSelfReference() = 0; // may return empty/default. not all heaps are sharable.
@ -155,4 +156,4 @@ protected:
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

@ -21,3 +21,13 @@ struct AuHeapAccessor
return pHeap->GetSelfReferenceRaw();
}
};
struct AuHeapAccessor2
{
protected:
template <typename Type>
inline static auto Get()
{
return &AuHeap::DeleteThat<Type>;
}
};

View File

@ -8,6 +8,91 @@
***/
#pragma once
//
// AuHUPOf_t<T> AuNewClassArrayUnique<T>([pHeap, ]uElements, ...)
// AuUPtr<T> AuNewClassArrayUnique<T>([pHeap, ]uElements, ...) [ 2024/09 ]
// AuSPtr<T> AuNewClassArray<T>([pHeap, ]uElements, ...)
// AuHUPOf_t<Z> AuNewClassUnique<T, Z = T>([pHeap, ] ...)
// AuUPtr<Z> AuNewClassUnique<T, Z = T>([pHeap, ] ...)
// sizeof( AuHUPOf_t<T> ) ==
// sizeof( AuUPtr<T> ) == [ 2024/09 ]
// 2 * sizeof( void * )
// AuHPtr<T> AuNewClassSmallUnique<T>([pHeap, ] ...) [ 2024/09 ]
// sizeof( AuHPtr<T> ) == sizeof( void * )
// AuSPtr<T> AuNewClass([pHeap, ] ...)
// sizeof(AuSPtr<T>) ~= 2x (void *)
// AuHUPOf_t<T> AuNullHeapPointer<T>()
// AuUPtr<T> AuNullHeapPointer<T>() [ 2024/09 ]
// AuSPtr<T> AuMakeShared(...)
//
// AuSPtr<T> - shared
//
// AuSSPtr<T> - 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<T> - unique with immutable instantiated deleter (...<T>) of derived main class (= T)
//
// AuHUPOf_t<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<T NO DELETER> to be compatible to pre 2024/09 codebases.
//
// AuUPtr<T, Deleter_t> - close to what youd expect from a std::unique_pointer with special edge cases.
//
// AuUPtr<T> - prior to 2024/09, invalid
// AuUPtr<T> - after 2024/09, an empty function callback unique pointer container. 2x void*
// - use me for maximum laziness
// after 2024/09:
// std::shared_ptr<T> a = { AuSPtr<T>() }
// std::unique_ptr<T, ...> a = { AuUPtr<T, ...>().Release(), AuUPtr<T, ...>().GetDeleter() }
// AuUPtr<T, ...> a = { std::unique_ptr<T, ...>().release(), std::unique_ptr<T, ...>().get_deleter() }
// AuSPtr<T> a = { std::shared_ptr<T>() }
// AuHUPOf_t<T> a = AuNullHeapPointer<T>() (2x void * sized container)
// AuUPtr<T> a = AuNullHeapPointer<T>() (2x void * sized container)
// AuHUPOf_t<T> a { AuMove(AuUPtr<T>) } (2x void * sized container)
// AuUPtr<T> a { AuMove(AuHUPOf_t<T>) } (2x void * sized container)
// AuUPtr<T> a { _new Kot() } (2x void * sized container)
// AuSPtr<T> a { AuMove(a) } (N/A Shared Pointer)
// AuHUPOf_t<T> a { } (2x void * sized container)
// AuUPtr<T> a { } (2x void * sized container)
// AuHUPOf_t<T> a = SomeAPI(...) (2x void * sized container)
// AuUPtr<T> a = SomeAPI(...) (2x void * sized container)
// AuUPtr<T> a = SOOObjectGenericUnique(...) (2x void * sized container)
// AuHUPOf_t<T> a = SOOObjectGenericUniqueOnHeap(pMyHeap, ...) (2x void * sized container)
// AuUPtr<T> a = SOOObjectGenericUniqueOnHeap(pMyHeap, ...) (2x void * sized container)
// AuUPtr<T,Deleter>|SOOOnHeapUnique_t a =
// SOOObjectUniqueOnHeap(pMyHeap, ...) (void* sized container)
// AuSPtr<T> a = SOOObjectSharedOnHeap(pMyHeap) (N/A Shared Pointer)
// SOOObject...cont as FuncName
// AuUPtr<T,Deleter>|FuncNameUnique_t a = FuncNameUnique() (void* sized container)
// AuUPtr<T> a = FuncNameGenericUnique() (2x void * sized container)
// AuUPtr<T,Deleter>|FuncNameSmallUnique_t a = FuncNameUnique() (void* sized container - old behaviour, lower overhead)
// AuHPtr<T> a = FuncNameGenericUnique() (void* sized container - old behaviour, lower overhead)
// AuSPtr<T> a = FuncNameShared() (N/A Shared Pointer)
// AuHPtrs of SmallUnique's are becoming the new AuHUPOf_t<T>()
// before 2024/09:
// std::shared_ptr<T> a = { AuSPtr<T>() }
// AuUPtr<T, ...> a = { std::unique_ptr<T, ...>().release(), std::unique_ptr<T, ...>().get_deleter() }
// AuSPtr<T> a = { std::shared_ptr<T>() }
// AuUPtr<T, AuDefaultDeleter<...>> a { _new Kot() } (void * sized container)
// AuHUPOf_t<T> a = AuNullHeapPointer<T>() (2x void * sized container)
// AuSPtr<T> a { AuMove(a) } (N/A Shared Pointer)
// AuHUPOf_t<T> a = pHeap->XXXXUnique(...) (2x void * sized container)
// AuHUPOf_t<T> a = AuNewXXXXUnique(...) (2x void * sized container)
// AuHUPOf_t<T> a = SomeAPI(...) (2x void * sized container)
// AuUPtr<T, ...> a = FuncNameUnique() (void* sized container)
// AuUPtr<T,Deleter>|FuncNameUnique_t a = FuncNameUnique() (void* sized container)
// AuSPtr<T> a = FuncNameShared() (N/A Shared Pointer)
// AuHPtr<T> - did not exist
// but still:
// AuHUPOf_t<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<T NO DELETER>.
// 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<T> 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<U> as implemented by <auROXTL/MemoryModel/auUniquePointer.hpp>.
// beforehand, AuUPtr<T> 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 <typename T>
using AuHUPOf_t = AuUPtr<T, void(*)(T *)>;
// cannot carry casts, is equal to sizeof(void *)
template <typename T>
using AuHSUPOf_t = AuUPtr<T, AuHeapUniqueDeleterClass<T>>;
// 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 <typename T>
using AuHPtr = AuHSUPOf_t<T>;
template <class T>
auto AuNullHeapPointer()
{
@ -114,10 +216,10 @@ 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)
template <class T, class Z = T, class ...Args>
AuHUPOf_t<Z> AuNewClassUnique(AuHeap *pHeap, Args &&...args)
{
return pHeap->NewClassUnique<T, Args...>(AuForward<Args>(args)...);
return pHeap->NewClassUnique<T, Z, Args...>(AuForward<Args>(args)...);
}
template <class T, class ...Args>
@ -126,6 +228,35 @@ AuSPtr<T> AuNewClass(AuHeap *pHeap, Args &&...args)
return pHeap->NewClass<T, Args...>(AuForward<Args>(args)...);
}
template <class T, class ...Args>
AuHPtr<T> AuNewClassUniqueSmall(AuHeap *pHeap, Args &&...args)
{
if (!pHeap)
{
return AuHPtr<T> {};
}
auto pThat = pHeap->NewClassUnique<T, T, Args...>(AuForward<Args>(args)...);
if (!pThat)
{
return AuHPtr<T> {};
}
auto pMyPointerNow = pThat.Release()->AsPointer();
_AUROXTL_DELETER_ASSERT(pThat, AuHeapUniqueDeleterClass<T>);
return AuHPtr<T> { pMyPointerNow };
}
template <class T, class ...Args>
AuHPtr<T> AuNewClassUniqueSmall(const AuSPtr<AuHeap> &pHeap, Args &&...args)
{
return AuNewClassUniqueSmall<T, Args...>(pHeap.get(), AuForward<Args>(args)...);
}
template <class T, class ...Args>
AuHPtr<T> AuNewClassUniqueSmall(Args &&...args)
{
return AuNewClassUniqueSmall<T, Args...>(__audetail::gDefaultDiscontiguousHeap, AuForward<Args>(args)...);
}
template <class T, class ...Args>
AuHUPOf_t<T> AuNewClassArrayUnique(const AuSPtr<AuHeap> &pHeap, AuUInt uElements, Args &&... fillCtr)
{

View File

@ -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<Type, extends>; \
using Type ## OnHeapUnique_t = AuUPtr<extends, CppDeleterSOOX ## Type>; \
using Type ## UniqueOnHeap_t = Type ## OnHeapUnique_t; \
using Type ## GenericUniqueOnHeap_t = AuUPtr<extends>; \
\
template <class ... T> \
AuUPtr<extends> Type ## UniqueOnHeap(AuHeap *pHeap, T &&... args) \
AuUPtr<extends> Type ## GenericUniqueOnHeap(AuHeap *pHeap, T &&... args) \
{ \
auto pThat = pHeap->NewClassUnique<Type>(AuForward<T>(args)...); \
if (!pThat) \
@ -127,6 +132,19 @@ using Type = Type ## SOO;
} \
\
template <class ... T> \
Type ## OnHeapUnique_t Type ## UniqueOnHeap(AuHeap *pHeap, T &&... args) \
{ \
auto pThat = pHeap->NewClassUnique<Type>(AuForward<T>(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 <class ... T> \
AuSPtr<extends> Type ## SharedOnHeap(AuHeap *pHeap, T &&... args) \
{ \
auto pThat = pHeap->NewClass<Type>(AuForward<T>(args)...); \

View File

@ -459,6 +459,7 @@ inline constexpr bool operator!=(const Aurora::Memory::BaseAuroraRuntimeAllocato
#include <auROXTL/MemoryModel/auHeapStats.hpp>
#include <auROXTL/MemoryModel/auHeap.hpp>
#include <auROXTL/MemoryModel/auHeapAccessor.hpp>
#include <auROXTL/MemoryModel/AuHeapUniqueDeleterClass.hpp>
#include <auROXTL/MemoryModel/auDummyHeap.hpp>