[+] AuMemory::Heap adapters for third party heap allocators
[+] AuMemory::HeapAdapterInterface to describe aforementioned heap allocators of a very limited API [+] AuMemory::HeapAdapter[Unique,Shared,] [+] HeapWin32Adapter to convert HANDLE hHeaps of win32s CreateHeap (RtlCreateHeap?) into AuMemory::Heaps
This commit is contained in:
parent
a995c37e81
commit
8be1afe570
@ -17,7 +17,7 @@ namespace Aurora::Memory
|
||||
struct CppHeapWrapper;
|
||||
|
||||
/**
|
||||
* Note: The following public aliases for heap or global process heap based allocations exist:
|
||||
* 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, ...)
|
||||
@ -168,6 +168,35 @@ namespace Aurora::Memory
|
||||
}
|
||||
};
|
||||
|
||||
struct HeapAdapterHandle
|
||||
{
|
||||
void *pReserved[2];
|
||||
};
|
||||
|
||||
struct HeapAdapterInterface
|
||||
{
|
||||
HeapAdapterHandle handle;
|
||||
|
||||
// Required:
|
||||
void *(* fAllocate)(HeapAdapterHandle *pHandle,
|
||||
AuUInt uLength,
|
||||
AuUInt uAlignment) = nullptr;
|
||||
|
||||
// Required:
|
||||
void (* fFree)(HeapAdapterHandle *pHandle,
|
||||
void *pPointer) = nullptr;
|
||||
|
||||
// Optional:
|
||||
AuUInt (* fGetBlockSize)(HeapAdapterHandle *pHandle,
|
||||
void *pPointer) = nullptr;
|
||||
|
||||
// Optional:
|
||||
void (* fHeapDestroy)(HeapAdapterHandle *pHandle) = nullptr;
|
||||
|
||||
//
|
||||
bool bHasAlignmentAwareness {};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a heap interface backed by the default allocator
|
||||
*/
|
||||
@ -189,29 +218,46 @@ namespace Aurora::Memory
|
||||
* @return a heap backed by uLength bytes of virtual memory
|
||||
* @warning the SOO variant cannot guarantee release-on-last-free and will panic if uLength cannot be allocated. Use AllocHeap[Shared/Unique/New](uLength) instead.
|
||||
*/
|
||||
AUKN_SHARED_SOO2_NCM(AllocHeap, Heap, kHeapSize, ((AuUInt, uLength)), AuUInt uLength);
|
||||
AUKN_SHARED_SOO2_NCM(AllocHeap, Heap, kHeapSize, ((AuUInt, uLength)),
|
||||
AuUInt uLength);
|
||||
|
||||
/**
|
||||
* @warning the SOO variant cannot guarantee release-on-last-free and will panic if an invalid memory handle is provided.
|
||||
*/
|
||||
AUKN_SHARED_SOO2_NCM(RequestHeapOfRegion, Heap, kHeapSize, ((const MemoryViewWrite &, memory)), const MemoryViewWrite &memory);
|
||||
AUKN_SHARED_SOO2_NCM(RequestHeapOfRegion, Heap, kHeapSize, ((const MemoryViewWrite &, memory)),
|
||||
const MemoryViewWrite &memory);
|
||||
|
||||
/**
|
||||
* @warning the SOO variant cannot guarantee release-on-last-free and will panic if an invalid memory handle is provided.
|
||||
*/
|
||||
AUKN_SHARED_SOO2_NCM(RequestHeapOfSharedRegion, Heap, kHeapSize, ((const AuSPtr<MemoryViewWrite> &, memory)), const AuSPtr<MemoryViewWrite> &pMemory);
|
||||
AUKN_SHARED_SOO2_NCM(RequestHeapOfSharedRegion, Heap, kHeapSize, ((const AuSPtr<MemoryViewWrite> &, memory)),
|
||||
const AuSPtr<MemoryViewWrite> &pMemory);
|
||||
|
||||
/**
|
||||
* Proxies an existing heap with encapsulated statistics.
|
||||
* This is intended for debugging purposes when accurate heap stats of a heap-subset are desired.
|
||||
* @warning this heap cannot guarantee release-on-last-free
|
||||
*/
|
||||
AUKN_SHARED_SOO2_NCM(HeapProxy, Heap, kHeap2Size, ((const AuSPtr<Heap> &, pHead)), const AuSPtr<Heap> &pHead);
|
||||
AUKN_SHARED_SOO2_NCM(HeapProxy, Heap, kHeap2Size, ((const AuSPtr<Heap> &, pHead)),
|
||||
const AuSPtr<Heap> &pHead);
|
||||
|
||||
/**
|
||||
* Proxies an existing heap with encapsulated statistics and leak detector
|
||||
* This is intended for debugging purposes when accurate heap stats of a heap-subset are desired.
|
||||
* @warning this heap cannot guarantee release-on-last-free
|
||||
*/
|
||||
AUKN_SHARED_SOO2_NCM(HeapProxyEx, Heap, kHeap2Size, ((const AuSPtr<Heap> &,pHead), (LeakFinderAlloc_f, pfAlloc), (LeakFinderFree_f, pfFree)), const AuSPtr<Heap> &pHead, LeakFinderAlloc_f pfAlloc, LeakFinderFree_f pfFree);
|
||||
AUKN_SHARED_SOO2_NCM(HeapProxyEx, Heap, kHeap2Size, ((const AuSPtr<Heap> &, pHead), (LeakFinderAlloc_f, pfAlloc), (LeakFinderFree_f, pfFree)),
|
||||
const AuSPtr<Heap> &pHead,
|
||||
LeakFinderAlloc_f pfAlloc,
|
||||
LeakFinderFree_f pfFree);
|
||||
|
||||
/**
|
||||
* Proxies an existing heap allocator library of a malloc and free; bonus points for aligned malloc, get allocation size, and destroy
|
||||
*/
|
||||
AUKN_SHARED_SOO2_NCM(HeapAdapter, Heap, kHeap2Size, ((const HeapAdapterInterface &, adapterInterface)),
|
||||
const HeapAdapterInterface &adapterInterface);
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
AUKN_SHARED_SOO2_NCM(HeapWin32Adapter, Heap, kHeap2Size, ((void *, hHeap)), void *hHeap);
|
||||
#endif
|
||||
}
|
83
Source/Memory/AuHeapAdapter.NT.cpp
Normal file
83
Source/Memory/AuHeapAdapter.NT.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuHeapAdapter.NT.cpp
|
||||
File: Heap.hpp
|
||||
Date: 2024-7-17
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuHeap.hpp"
|
||||
#include "AuHeapAdapter.hpp"
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
static void *Win32HeapAllocate(HeapAdapterHandle *pHandle,
|
||||
AuUInt uLength,
|
||||
AuUInt uAlignment)
|
||||
{
|
||||
auto hHandle = (HANDLE)pHandle->pReserved[0];
|
||||
return HeapAlloc(hHandle, 0, uLength);
|
||||
}
|
||||
|
||||
static void Win32HeapFree(HeapAdapterHandle *pHandle,
|
||||
void *pPointer)
|
||||
{
|
||||
auto hHandle = (HANDLE)pHandle->pReserved[0];
|
||||
HeapFree(hHandle, 0, pPointer);
|
||||
}
|
||||
|
||||
struct Win32HeapAllocator : ImplHeapAdapter
|
||||
{
|
||||
Win32HeapAllocator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Win32HeapAllocator(void *hHeap)
|
||||
{
|
||||
if (!this->Init(hHeap))
|
||||
{
|
||||
AU_THROW_CONST_STRING("Invalid heap adapter configuration");
|
||||
}
|
||||
}
|
||||
|
||||
bool Init(void *hHeap)
|
||||
{
|
||||
if (!hHeap)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
HeapAdapterInterface heap;
|
||||
heap.handle.pReserved[0] = hHeap;
|
||||
heap.fFree = Win32HeapFree;
|
||||
heap.fAllocate = Win32HeapAllocate;
|
||||
return ImplHeapAdapter::Init(heap);
|
||||
}
|
||||
};
|
||||
|
||||
AUKN_SYM Heap *HeapWin32AdapterNew(void *hHeap)
|
||||
{
|
||||
auto pHeap = _new Win32HeapAllocator();
|
||||
if (!pHeap)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!pHeap->Init(hHeap))
|
||||
{
|
||||
delete pHeap;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pHeap;
|
||||
}
|
||||
|
||||
AUKN_SYM void HeapWin32AdapterRelease(Heap *pHeap)
|
||||
{
|
||||
static_cast<Win32HeapAllocator *>(pHeap)->RequestTermination();
|
||||
}
|
||||
|
||||
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, HeapWin32Adapter, Win32HeapAllocator, (void *, hHeap))
|
||||
}
|
9
Source/Memory/AuHeapAdapter.NT.hpp
Normal file
9
Source/Memory/AuHeapAdapter.NT.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuHeapAdapter.NT.hpp
|
||||
File: Heap.hpp
|
||||
Date: 2024-7-17
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
280
Source/Memory/AuHeapAdapter.cpp
Normal file
280
Source/Memory/AuHeapAdapter.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
/***
|
||||
Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuHeapAdapter.cpp
|
||||
File: Heap.hpp
|
||||
Date: 2024-7-17
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuHeap.hpp"
|
||||
#include "AuHeapAdapter.hpp"
|
||||
#include "AuHeapInternal.hpp"
|
||||
#include "AuHeapDeletable.hpp"
|
||||
#include "AuHeapAlignmentInterface.hpp"
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
ImplHeapAdapter::ImplHeapAdapter(const HeapAdapterInterface &heapInterface)
|
||||
{
|
||||
if (!this->Init(heapInterface))
|
||||
{
|
||||
AU_THROW_CONST_STRING("Invalid heap adapter configuration");
|
||||
}
|
||||
}
|
||||
|
||||
ImplHeapAdapter::ImplHeapAdapter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ImplHeapAdapter::~ImplHeapAdapter()
|
||||
{
|
||||
if (this->adapter.fHeapDestroy)
|
||||
{
|
||||
this->adapter.fHeapDestroy(&this->adapter.handle);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImplHeapAdapter::Init(const HeapAdapterInterface &heapInterface)
|
||||
{
|
||||
this->adapter = heapInterface;
|
||||
|
||||
if (!this->adapter.fFree ||
|
||||
!this->adapter.fAllocate)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->adapter.fGetBlockSize ||
|
||||
!this->adapter.bHasAlignmentAwareness)
|
||||
{
|
||||
if (!MakeHeapInterfaceOfStricterAlignment(&this->adapter))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HeapStats &ImplHeapAdapter::GetStats()
|
||||
{
|
||||
return this->stats;
|
||||
}
|
||||
|
||||
Types::size_t ImplHeapAdapter::GetChunkSize(const void *head)
|
||||
{
|
||||
if (!head)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return this->adapter.fGetBlockSize(&this->adapter.handle, (void *)head);
|
||||
}
|
||||
|
||||
AuSPtr<Heap> ImplHeapAdapter::AllocateDivision(AuUInt32 heap, AuUInt32 alignment)
|
||||
{
|
||||
return AllocateDivisionGlobal(this, heap, alignment);
|
||||
}
|
||||
|
||||
void *ImplHeapAdapter::_FAlloc(Types::size_t uLength)
|
||||
{
|
||||
return _FAlloc(uLength, alignof(void *));
|
||||
}
|
||||
|
||||
void *ImplHeapAdapter::_FAlloc(Types::size_t uLength, Types::size_t uAlign)
|
||||
{
|
||||
if (!uLength)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto pRet = this->adapter.fAllocate(&this->adapter.handle, uLength, uAlign);
|
||||
if (!pRet)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto uLengthCurrent = this->GetChunkSize(pRet);
|
||||
|
||||
AuAtomicAdd(&this->stats.uBytesLiveCounter, uLengthCurrent);
|
||||
AuAtomicAdd(&this->stats.uBytesAllocatedLifetime, uLengthCurrent);
|
||||
|
||||
return pRet;
|
||||
}
|
||||
|
||||
void *ImplHeapAdapter::_ZAlloc(Types::size_t uLength)
|
||||
{
|
||||
auto ptr = this->_FAlloc(uLength);
|
||||
if (!ptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AuMemset(ptr, 0, uLength);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *ImplHeapAdapter::_ZAlloc(Types::size_t uLength, Types::size_t uAlign)
|
||||
{
|
||||
auto ptr = this->_FAlloc(uLength, uAlign);
|
||||
if (!ptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AuMemset(ptr, 0, uLength);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *ImplHeapAdapter::_ZRealloc(void *pBuffer, Types::size_t uLength)
|
||||
{
|
||||
auto prevLength = this->GetChunkSize(pBuffer);
|
||||
auto alloc = this->_ZAlloc(uLength);
|
||||
if (!alloc)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AuMemcpy(alloc, pBuffer, AuMin(prevLength, uLength));
|
||||
this->_Free(pBuffer);
|
||||
return alloc;
|
||||
}
|
||||
|
||||
void *ImplHeapAdapter::_ZRealloc(void *pBuffer, Types::size_t uLength, Types::size_t uAlign)
|
||||
{
|
||||
auto prevLength = this->GetChunkSize(pBuffer);
|
||||
auto alloc = this->_ZAlloc(uLength, uAlign);
|
||||
if (!alloc)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AuMemcpy(alloc, pBuffer, AuMin(prevLength, uLength));
|
||||
this->_Free(pBuffer);
|
||||
return alloc;
|
||||
}
|
||||
|
||||
void *ImplHeapAdapter::_FRealloc(void *pBuffer, Types::size_t uLength)
|
||||
{
|
||||
auto prevLength = this->GetChunkSize(pBuffer);
|
||||
auto alloc = this->_FAlloc(uLength);
|
||||
if (!alloc)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AuMemcpy(alloc, pBuffer, AuMin(prevLength, uLength));
|
||||
this->_Free(pBuffer);
|
||||
return alloc;
|
||||
}
|
||||
|
||||
void *ImplHeapAdapter::_FRealloc(void *pBuffer, Types::size_t uLength, Types::size_t uAlign)
|
||||
{
|
||||
auto prevLength = this->GetChunkSize(pBuffer);
|
||||
auto alloc = this->_FAlloc(uLength, uAlign);
|
||||
if (!alloc)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AuMemcpy(alloc, pBuffer, AuMin(prevLength, uLength));
|
||||
this->_Free(pBuffer);
|
||||
return alloc;
|
||||
}
|
||||
|
||||
void ImplHeapAdapter::_Free(void *pBuffer)
|
||||
{
|
||||
if (pBuffer == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto uLengthCurrent = this->GetChunkSize(pBuffer);
|
||||
|
||||
this->adapter.fFree(&this->adapter.handle, pBuffer);
|
||||
|
||||
AuAtomicAdd(&this->stats.uBytesFreeLifetime, uLengthCurrent);
|
||||
AuAtomicSub(&this->stats.uBytesLiveCounter, uLengthCurrent);
|
||||
|
||||
TryRelease();
|
||||
}
|
||||
|
||||
void ImplHeapAdapter::TryRelease()
|
||||
{
|
||||
if (!this->bIsDangling_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AuAtomicLoad(&this->stats.uBytesLiveCounter) == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void ImplHeapAdapter::RequestTermination()
|
||||
{
|
||||
if (AuAtomicLoad(&this->stats.uBytesLiveCounter))
|
||||
{
|
||||
SysPushErrorMemory("Heap life was less than its allocations, waiting for final free");
|
||||
SysPushErrorMemory("Reporting using mayday!");
|
||||
|
||||
// Write a crash dump for later review, and do not panic.
|
||||
// We just have a leak with no sign of corruption
|
||||
Telemetry::Mayday();
|
||||
|
||||
this->bIsDangling_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void ImplHeapAdapter::WalkHeap(bool(*fCallback)(void *, void *), void *pSecondArg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AuSPtr<Heap> ImplHeapAdapter::GetSelfReference()
|
||||
{
|
||||
try
|
||||
{
|
||||
return AuSharedFromThis();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Heap *ImplHeapAdapter::GetSelfReferenceRaw()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
AUKN_SYM Heap *HeapAdapterNew(const HeapAdapterInterface &adapterInterface)
|
||||
{
|
||||
auto pHeap = _new ImplHeapAdapter();
|
||||
if (!pHeap)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!pHeap->Init(adapterInterface))
|
||||
{
|
||||
delete pHeap;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pHeap;
|
||||
}
|
||||
|
||||
AUKN_SYM void HeapAdapterRelease(Heap *pHeap)
|
||||
{
|
||||
static_cast<ImplHeapAdapter *>(pHeap)->RequestTermination();
|
||||
}
|
||||
|
||||
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, HeapAdapter, ImplHeapAdapter, (const HeapAdapterInterface &, adapterInterface))
|
||||
}
|
60
Source/Memory/AuHeapAdapter.hpp
Normal file
60
Source/Memory/AuHeapAdapter.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
/***
|
||||
Copyright (C) 2021-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuHeapAdapter.hpp
|
||||
File: Heap.hpp
|
||||
Date: 2024-7-17
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "AuMemory.hpp"
|
||||
#include "AuBaseHeap.hpp"
|
||||
|
||||
#include "o1heap.hpp"
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
struct ImplHeapAdapter :
|
||||
Heap,
|
||||
AuEnableSharedFromThis<ImplHeapAdapter>
|
||||
{
|
||||
virtual AuSPtr<Heap> AllocateDivision(AuUInt32 heap, AuUInt32 alignment) override;
|
||||
|
||||
ImplHeapAdapter();
|
||||
ImplHeapAdapter(const HeapAdapterInterface &heapInterface);
|
||||
virtual ~ImplHeapAdapter();
|
||||
|
||||
bool Init(const HeapAdapterInterface &heapInterface);
|
||||
|
||||
Types::size_t GetChunkSize(const void *head) override;
|
||||
|
||||
void *_FAlloc(Types::size_t uLength) override;
|
||||
void *_FAlloc(Types::size_t uLength, Types::size_t uAlign) override;
|
||||
void *_ZAlloc(Types::size_t uLength) override;
|
||||
void *_ZAlloc(Types::size_t uLength, Types::size_t uAlign) override;
|
||||
void *_ZRealloc(void *pBuffer, Types::size_t uLength) override;
|
||||
void *_ZRealloc(void *pBuffer, Types::size_t uLength, Types::size_t uAlign) override;
|
||||
void *_FRealloc(void *pBuffer, Types::size_t uLength) override;
|
||||
void *_FRealloc(void *pBuffer, Types::size_t uLength, Types::size_t uAlign) override;
|
||||
void _Free(void *pBuffer) override;
|
||||
AuSPtr<Heap> GetSelfReference() override;
|
||||
Heap *GetSelfReferenceRaw() override;
|
||||
|
||||
void TryRelease();
|
||||
void RequestTermination();
|
||||
|
||||
void WalkHeap(bool(*fCallback)(void *, void *), void *pSecondArg) override;
|
||||
|
||||
HeapStats &GetStats() override;
|
||||
|
||||
private:
|
||||
HeapStats stats;
|
||||
HeapAdapterInterface adapter;
|
||||
|
||||
protected:
|
||||
bool bOwnsMemory_ {};
|
||||
bool bIsDangling_ {};
|
||||
|
||||
};
|
||||
}
|
92
Source/Memory/AuHeapAlignmentInterface.cpp
Normal file
92
Source/Memory/AuHeapAlignmentInterface.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuHeapAlignmentInterface.cpp
|
||||
File: Heap.hpp
|
||||
Date: 2024-7-17
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "AuHeap.hpp"
|
||||
#include "AuHeapAlignmentInterface.hpp"
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
struct OldHeap
|
||||
{
|
||||
HeapAdapterInterface interface;
|
||||
};
|
||||
|
||||
static void *AlignedHeapAllocate(HeapAdapterHandle *pHandle,
|
||||
AuUInt uLength,
|
||||
AuUInt uAlignment)
|
||||
{
|
||||
auto pInterface = (OldHeap *)pHandle->pReserved[0];
|
||||
|
||||
uAlignment = AuNextPow2(uAlignment);
|
||||
|
||||
const auto kAlignment = AuMax(uAlignment, sizeof(void *) * 2);
|
||||
|
||||
auto pPtr = (AuUInt8 *)pInterface->interface.fAllocate(&pInterface->interface.handle, uLength + (kAlignment * 2), kAlignment);
|
||||
|
||||
if (!pPtr)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto pRet = (AuUInt8 *)AuPageRoundUp(AuUInt(pPtr + kAlignment), uAlignment);
|
||||
auto pSize = pRet - (sizeof(void *) * 2);
|
||||
auto pDelta = pRet - (sizeof(void *) * 1);
|
||||
|
||||
*(AuUInt *)pSize = uLength;
|
||||
*(AuUInt *)pDelta = AuUInt(pPtr);
|
||||
return pRet;
|
||||
}
|
||||
|
||||
static void AlignedHeapFree(HeapAdapterHandle *pHandle,
|
||||
void *pPointer)
|
||||
{
|
||||
auto pInterface = (OldHeap *)pHandle->pReserved[0];
|
||||
|
||||
auto pRet = (AuUInt8 *)pPointer;
|
||||
auto pDelta = pRet - (sizeof(void *) * 1);
|
||||
|
||||
pInterface->interface.fFree(&pInterface->interface.handle, *(void **)pDelta);
|
||||
}
|
||||
|
||||
static AuUInt AlignedHeapGetBlockSize(HeapAdapterHandle *pHandle,
|
||||
void *pPointer)
|
||||
{
|
||||
auto pRet = (AuUInt8 *)pPointer;
|
||||
auto pSize = pRet - (sizeof(void *) * 2);
|
||||
return *(AuUInt *)pSize;
|
||||
}
|
||||
|
||||
static void AlignedHeapDestroy(HeapAdapterHandle *pHandle)
|
||||
{
|
||||
auto pInterface = (OldHeap *)pHandle->pReserved[0];
|
||||
if (pInterface->interface.fHeapDestroy)
|
||||
{
|
||||
pInterface->interface.fHeapDestroy(&pInterface->interface.handle);
|
||||
}
|
||||
delete pInterface;
|
||||
}
|
||||
|
||||
bool MakeHeapInterfaceOfStricterAlignment(HeapAdapterInterface *pInterface)
|
||||
{
|
||||
auto pNew = _new OldHeap();
|
||||
if (!pNew)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pNew->interface = *pInterface;
|
||||
|
||||
pInterface->handle.pReserved[0] = pNew;
|
||||
pInterface->fHeapDestroy = AlignedHeapDestroy;
|
||||
pInterface->fGetBlockSize = AlignedHeapGetBlockSize;
|
||||
pInterface->fFree = AlignedHeapFree;
|
||||
pInterface->fAllocate = AlignedHeapAllocate;
|
||||
return true;
|
||||
}
|
||||
}
|
14
Source/Memory/AuHeapAlignmentInterface.hpp
Normal file
14
Source/Memory/AuHeapAlignmentInterface.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
/***
|
||||
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: AuHeapAlignmentInterface.hpp
|
||||
File: Heap.hpp
|
||||
Date: 2024-7-17
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::Memory
|
||||
{
|
||||
bool MakeHeapInterfaceOfStricterAlignment(HeapAdapterInterface *pInterface);
|
||||
}
|
Loading…
Reference in New Issue
Block a user