/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Heap.hpp Date: 2021-6-9 Author: Reece ***/ #pragma once namespace Aurora::Memory { struct ProxyHeap; static const AuUInt8 kHeapSize = 128; static const AuUInt8 kHeap2Size = 255; template struct CppHeapWrapper; /** * Note: The following public aliases for heap or global process heap based allocations exist: * * AuHUPOf_t AuNewClassArrayUnique([pHeap, ]uElements, ...) * AuSPtr AuNewClassArray([pHeap, ]uElements, ...) * AuHUPOf_t AuNewClassUnique([pHeap, ] ...) * AuSPtr AuNewClass([pHeap, ] ...) * AuHUPOf_t AuNullHeapPointer() */ struct Heap { virtual AuSPtr AllocateDivision(AuUInt32 heap, AuUInt32 alignment = 32) = 0; virtual Types::size_t GetChunkSize(const void *pHead) = 0; virtual HeapStats &GetStats() = 0; virtual void WalkHeap(bool(*fCallback)(void *, void *), void *pSecondArg) = 0; /// Potentially slower, zero allocate template T ZAlloc(Types::size_t uLength); /// POD zero allocation template T ZAlloc(Types::size_t uLength, Types::size_t uAlignment); /// POD zero allocation template T *ZAlloc(); /// POD array, zero allocation template T *NewArray(Types::size_t uLength); /// POD array, zero allocation template T *NewArray(Types::size_t uLength, Types::size_t uAlignment); /// Fast, POD, non-zeroing allocation template T FAlloc(Types::size_t uLength); /// Fast, POD, non-zeroing allocation template T FAlloc(Types::size_t uLength, Types::size_t uAlignment); /// Fast, POD, non-zeroing allocation template T *FAlloc(); // Reallocs /// POD, zero-based expansion or reallocation template T ZRealloc(T pHead, Types::size_t uLength); /// POD, zero-based expansion or reallocation template T ZRealloc(T pHead, Types::size_t uLength, Types::size_t uAlignment); /// POD, expansion or reallocation template T FRealloc(T pHead, Types::size_t uLength); /// POD, expansion or reallocation template T FRealloc(T pHead, Types::size_t uLength, Types::size_t uAlignment); /// Free template void Free(T pHead); protected: template static void DeleteThat(T *pThat); template static void DeleteThatArray(T *pThat); template static void DeleteThatCastedOnce(T *pThat); template static void RetardedSpecWrittenByRetards(T *pThat); public: template AuSPtr NewClass(Args &&...args); // note: callers can use AuHUPOf_t pUniquePointer = AuNullHeapPointer() template AuUPtr)> NewClassUnique(Args &&...args); template AuSPtr NewClassArray(AuUInt uElements, Args &&... fillCtr); template AuSPtr NewClassArray2(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr); // note: callers can use AuHUPOf_t pUniquePointer = AuNullHeapPointer() template AuUPtr)> NewClassArrayUnique(AuUInt uElements, Args &&... fillCtr); template AuUPtr)> NewClassArray2Unique(AuUInt uElements, AuUInt uAlignment, Args &&... fillCtr); template cstatic AuUPtr)> NullUniquePointer(); template cstatic AuUPtr)> CastPointer(AuUPtr)> &&pInPointer); template using HUPOf_t = AuUPtr)>; protected: friend struct ProxyHeap; friend struct HeapAccessor; virtual AuSPtr GetSelfReference() = 0; // may return empty/default. not all heaps are sharable. virtual Heap *GetSelfReferenceRaw() = 0; virtual AU_ALLOC void *_ZAlloc(Types::size_t uLength) = 0; virtual AU_ALLOC void *_ZAlloc(Types::size_t uLength, Types::size_t uAlignment) = 0; virtual AU_ALLOC void *_FAlloc(Types::size_t uLength) = 0; virtual AU_ALLOC void *_FAlloc(Types::size_t uLength, Types::size_t uAlignment) = 0; virtual AU_ALLOC void *_ZRealloc(void *pBase, Types::size_t uLength, Types::size_t uAlign) = 0; virtual AU_ALLOC void *_ZRealloc(void *pBase, Types::size_t uLength) = 0; virtual AU_ALLOC void *_FRealloc(void *pBase, Types::size_t uLength, Types::size_t uAlign) = 0; virtual AU_ALLOC void *_FRealloc(void *pBase, Types::size_t uLength) = 0; virtual void _Free(void* pBase) = 0; }; struct HeapAccessor { cstatic AuSPtr GetSelfReference(Heap *pHeap) { return pHeap->GetSelfReference(); } cstatic Heap *GetSelfReferenceRaw(Heap *pHeap) { return pHeap->GetSelfReferenceRaw(); } }; /** * Returns a heap interface backed by the default allocator */ AUKN_SHARED_API(DefaultDiscontiguousHeap, Heap); inline Heap *GetDefaultDiscontiguousHeap() { return DefaultDiscontiguousHeapNew(); } inline AuSPtr GetDefaultDiscontiguousHeapShared() { // Might not allocate the control block under some STLs, unlike DefaultDiscontiguousHeapSharedShared() which will generally always allocate a control block under most STLs return AuUnsafeRaiiToShared(GetDefaultDiscontiguousHeap()); } /** * Allocates uLength amount of contiguous virtual 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); /** * @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); /** * @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 &, memory)), const AuSPtr &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 &, pHead)), const AuSPtr &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 &,pHead), (LeakFinderAlloc_f, pfAlloc), (LeakFinderFree_f, pfFree)), const AuSPtr &pHead, LeakFinderAlloc_f pfAlloc, LeakFinderFree_f pfFree); }