AuROXTL/Include/auROXTL/auMemoryModel.hpp

413 lines
9.4 KiB
C++
Raw Normal View History

2022-04-01 04:06:53 +00:00
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auMemoryModel.hpp
Date: 2022-2-1
File: AuroraUtils.hpp
File: auROXTLUtils.hpp
Date: 2021-6-9
Author: Reece
***/
#pragma once
#include "auTypes.hpp"
#if !defined(AURORA_RUNTIME_AU_SHARED_PTR)
#define AURORA_RUNTIME_AU_SHARED_PTR std::shared_ptr
#endif
#if !defined(AURORA_RUNTIME_AU_WEAK_PTR)
#define AURORA_RUNTIME_AU_WEAK_PTR std::weak_ptr
#endif
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
#endif
#if !defined(AURORA_RUNTIME_AU_DEFAULT_DELETER)
#define AURORA_RUNTIME_AU_DEFAULT_DELETER std::default_delete
#endif
template <class T>
using AuDefaultDeleter = AURORA_RUNTIME_AU_DEFAULT_DELETER<T>;
#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>
using AuUPtr = AURORA_RUNTIME_AU_UNIQUE_PTR<T, Deleter_t>;
#if !defined(AU_AuEnableSharedFromThis)
#define AU_AuEnableSharedFromThis
template <class X>
struct AuEnableSharedFromThis : Aurora::Memory::ExSharedFromThis<X, std::enable_shared_from_this<X>>
{};
#endif
#if !defined(AURORA_RUNTIME_MAKE_SHARED)
#define AURORA_RUNTIME_MAKE_SHARED std::make_shared
#endif
2024-02-16 10:28:14 +00:00
static inline AU_NORETURN void SysPanic(const char *pMsg);
static auline void AuMemoryPanic(const char *msg)
{
#if defined(AURORA_RUNTIME_MEMORY_PANIC)
AURORA_RUNTIME_MEMORY_PANIC(msg);
#else
2024-02-16 10:28:14 +00:00
SysPanic(msg);
#endif
}
2022-04-01 04:06:53 +00:00
template <class T, typename... Args>
static auline AuSPtr<T> AuMakeShared(Args&&... args)
{
try
{
return AURORA_RUNTIME_MAKE_SHARED<T>(AuForward<Args>(args)...);
}
catch (...)
{
return {};
}
}
template <class T, typename... Args>
static auline AuSPtr<T> AuMakeSharedPanic(Args&&... args)
{
try
{
auto pShared = AURORA_RUNTIME_MAKE_SHARED<T>(AuForward<Args>(args)...);
if (!pShared)
{
AuMemoryPanic("Failed to allocate <X>"); // TODO: non-rtti typename
}
return pShared;
}
catch (...)
{
AuMemoryPanic("Failed to allocate <X>"); // TODO: non-rtti typename
return {};
}
}
template <class T, typename... Args>
static auline AuSPtr<T> AuMakeSharedThrow(Args&&... args)
{
try
{
auto pShared = AURORA_RUNTIME_MAKE_SHARED<T>(AuForward<Args>(args)...);
if (!pShared)
{
// TODO: Agnostic SysPushErrorMemory
AU_THROW_STRING("Failed to allocate <X>"); // TODO: non-rtti typename
}
return pShared;
}
catch (...)
{
// TODO: Agnostic SysPushErrorCatch
AU_THROW_STRING("Failed to allocate <X>"); // TODO: non-rtti typename
return {};
}
}
2022-04-01 04:06:53 +00:00
namespace __audetail
{
struct Dummy
{
char a;
};
inline AuSPtr<Dummy> GetDummyDeleter()
{
static AuSPtr<Dummy> d;
if (!d)
{
#if defined(AURORA_COMPILER_MSVC)
return d;
#endif
d = AuMakeShared<Dummy>();
}
return d;
}
}
template <class T>
static auline AuSPtr<T> AuMakeSharedArray(AuUInt count)
{
try
{
#if defined(AU_LANG_CPP_20) && 0
return AURORA_RUNTIME_AU_SHARED_PTR<T[]>(count);
#else
return AURORA_RUNTIME_AU_SHARED_PTR<T>(new T[count], AuDefaultDeleter<T[]>());
#endif
}
catch (...)
{
return {};
}
}
template <class T>
static AuSPtr<T> AuUnsafeRaiiToShared(T *in)
{
return AuSPtr<T>(__audetail::GetDummyDeleter(), in);
}
template <class T, class Z>
static AuSPtr<T> AuUnsafeRaiiToShared(const AuUPtr<T, Z> &in)
{
return AuUnsafeRaiiToShared(in.get());
}
template <class T, AuUInt Z>
static constexpr AuUInt AuArraySize(const T(&array)[Z])
2022-04-01 04:06:53 +00:00
{
return Z;
}
2023-02-04 23:54:19 +00:00
template <typename T, typename C>
2023-04-06 14:04:36 +00:00
static AuUInt AuOffsetOf(C T:: *offset)
2023-02-04 23:54:19 +00:00
{
return AuUInt(
&(((const T *)(nullptr))->*offset)
);
2023-04-06 14:04:36 +00:00
}
template <typename T>
static auto AuTryLockMemoryType(T weak) -> decltype(weak.lock())
{
if (weak.expired())
{
return {};
}
AUROXTL_COMMODITY_TRY
{
return weak.lock();
}
AUROXTL_COMMODITY_CATCH
{
return {};
}
2023-02-04 23:54:19 +00:00
}
template <typename T>
constexpr AuUInt AuSizeOf()
{
return sizeof(T);
}
template <typename T>
constexpr AuUInt AuSizeOf(const T &)
{
return sizeof(T);
}
template <typename T>
constexpr AuUInt AuSizeOf(const T *)
{
return sizeof(T);
}
template <typename T>
constexpr AuUInt AuSizeOf(const AuSPtr<T>)
{
return sizeof(T);
}
2022-04-01 04:06:53 +00:00
template <class Z, typename T>
static void auline AuSafeDelete(T *in)
{
static_assert(AuIsBaseOf_v<T, AuRemovePointer_t<Z>>, "Couldn't not safe delete from type T because it is not derived from Z");
if (in == nullptr)
{
return;
2022-04-01 04:06:53 +00:00
}
delete static_cast<Z>(in);
}
2022-04-04 06:55:47 +00:00
// TODO: Move me
#include "auOptional.hpp"
#include "auCastUtils.hpp"
2022-04-01 04:06:53 +00:00
namespace Aurora::Memory
{
template <class T>
struct CppHeapWrapper;
2022-04-01 04:06:53 +00:00
#if defined(AURORA_ROXTL_ALLOCATORS_USE_STD)
template<typename T>
using PrimitiveArrayAllocator = std::allocator<T>;
template<typename T>
using ClassArrayAllocator = std::allocator<T>;
template<typename T>
using StringAllocator = std::allocator<T>;
#else
static void *__FAlloc(Types::size_t length, Types::size_t align);
static void __Free(void *buffer);
2024-04-20 21:37:52 +00:00
static AuUInt __SizeOf(void *pHead);
2022-04-01 04:06:53 +00:00
template <class T>
struct BaseAuroraRuntimeAllocator
{
typedef T value_type;
AU_COPY_MOVE(BaseAuroraRuntimeAllocator)
constexpr BaseAuroraRuntimeAllocator()
{}
2024-04-20 21:37:52 +00:00
template <class U>
constexpr BaseAuroraRuntimeAllocator(const BaseAuroraRuntimeAllocator <U> &) noexcept
2022-04-01 04:06:53 +00:00
{
}
2024-04-20 21:37:52 +00:00
void *allocate_bytes(std::size_t nbytes,
std::size_t alignment = alignof(std::max_align_t))
2022-04-01 04:06:53 +00:00
{
2024-04-20 21:37:52 +00:00
if (auto pRet = __FAlloc(nbytes, alignment))
2022-04-01 04:06:53 +00:00
{
2024-04-20 21:37:52 +00:00
return pRet;
2022-04-01 04:06:53 +00:00
}
2024-04-20 21:37:52 +00:00
else
{
throw std::bad_alloc();
}
}
void deallocate_bytes(void *p,
std::size_t nbytes,
std::size_t alignment = alignof(std::max_align_t))
{
return __Free(p);
}
#if defined(AU_LANG_CPP_23)
constexpr std::allocation_result<T *> allocate_at_least(const size_t count)
{
auto pThat = this->allocate(count);
return { (T *)pThat, __SizeOf(pThat) / sizeof(T) };
}
#endif
template <class U, class... Args >
void construct(U *p, Args&&... args)
{
2024-04-21 05:04:37 +00:00
new ((void *)p) U(AuForward<Args>(args)...);
2024-04-20 21:37:52 +00:00
}
template <class U, class... Args >
void construct_at(U *p, Args&&... args)
{
2024-04-21 05:04:37 +00:00
new ((void *)p) U(AuForward<Args>(args)...);
2024-04-20 21:37:52 +00:00
}
2024-04-21 05:04:37 +00:00
void deallocate(const T *pType,
2024-04-20 21:37:52 +00:00
const size_t count)
{
this->deallocate_bytes((void *)pType, 0, 0);
}
2024-04-21 05:04:37 +00:00
AU_ALLOC T *allocate(const size_t count)
2024-04-20 21:37:52 +00:00
{
if (!count)
{
return nullptr;
}
return (T *)this->allocate_bytes(count * sizeof(T), alignof(T));
}
2022-04-01 04:06:53 +00:00
2024-04-20 21:37:52 +00:00
template <class U>
U *allocate_object(std::size_t n = 1)
{
return (U *)this->allocate_bytes(sizeof(U) * n, alignof(U));
2022-04-01 04:06:53 +00:00
}
2024-04-20 21:37:52 +00:00
template <class U>
void deallocate_object(U *p, std::size_t n = 1)
2022-04-01 04:06:53 +00:00
{
2024-04-20 21:37:52 +00:00
this->deallocate_bytes(p, 0, 0);
}
template <class U, class... CtorArgs>
U *new_object(CtorArgs&&... args)
{
U *p = this->allocate_object<U>();
2024-04-21 05:04:37 +00:00
try
2024-04-20 21:37:52 +00:00
{
2024-04-21 05:04:37 +00:00
this->construct(p, AuForward<CtorArgs>(args)...);
}
catch (...)
{
this->deallocate_object(p);
throw;
2024-04-20 21:37:52 +00:00
}
return p;
}
template <class U>
void delete_object(U *p)
{
if constexpr (AuIsClass_v<U> &&
!AuIsTriviallyDestructible_v<U>)
{
p->~U();
}
this->deallocate_object(p);
2022-04-01 04:06:53 +00:00
}
2024-05-07 04:12:46 +00:00
template <class Z>
inline constexpr bool operator==(const Aurora::Memory::BaseAuroraRuntimeAllocator<Z> &rhs) noexcept
{
return true;
}
2022-04-01 04:06:53 +00:00
};
template<typename T>
using PrimitiveArrayAllocator = BaseAuroraRuntimeAllocator<T>;
template<typename T>
using ClassArrayAllocator = BaseAuroraRuntimeAllocator<T>;
template<typename T>
using StringAllocator = BaseAuroraRuntimeAllocator<T>;
#endif
2024-04-28 10:56:30 +00:00
}
template <class T, class Z>
2024-05-07 04:12:46 +00:00
inline constexpr bool operator==(const Aurora::Memory::BaseAuroraRuntimeAllocator<T> &lhs,
const Aurora::Memory::BaseAuroraRuntimeAllocator<Z> &rhs) noexcept
2024-04-28 10:56:30 +00:00
{
return true;
2024-05-07 04:12:46 +00:00
}
template <class T, class Z>
inline constexpr bool operator!=(const Aurora::Memory::BaseAuroraRuntimeAllocator<T> &lhs,
const Aurora::Memory::BaseAuroraRuntimeAllocator<Z> &rhs) noexcept
{
return false;
}