[*] Added an option for leaking strong heap pointers (ToSmartPointer)

This commit is contained in:
Reece Wilson 2022-01-18 19:31:15 +00:00
parent 62aecf3308
commit 413d3968ad
3 changed files with 55 additions and 19 deletions

View File

@ -87,34 +87,48 @@ namespace Aurora::Memory
_Free(reinterpret_cast<void *>(in));
}
/**
* @brief
* @param in
* A pointer owned by the heap
* @param pinThis
* If you attempt to destroy a heap, or allow a shared ptr to free the heap w/o freeing all allocations, the heap will dangle and a telemetry warning will be sent.
* pinThis isn't strictly needed unless you wish to slience heap freed before allocation warnings.
* A memory management model whereby you dont pin the parent heap will prevent circular references from taking over; in contrast, the alternative will need well defined object disposal
* One could keep heap references weak outside of your heap manager and always pin this - or you could pin nothing and be careful with object disposal order
* @return
*/
template<typename T>
AuSPtr<T> ToSmartPointer(T *in)
AuSPtr<T> ToSmartPointer(T *in, bool pinThis = true)
{
if (in == nullptr) return {};
return
std::shared_ptr<T>(in,
[=](T *delt)
{
if constexpr (std::is_class_v<T>)
{
delt->~T();
}
this->Free(delt);
});
auto heapHandle = pinThis ? GetSelfReference() : {};
return std::shared_ptr<T>(in,
[heapHandle, in, this](T *delt)
{
if constexpr (std::is_class_v<T>)
{
delt->~T();
}
this->Free(delt);
});
}
template<typename T>
static AuSPtr<T> ToSmartPointer(AuSPtr<Heap> heap, T *in)
static AuSPtr<T> ToSmartPointer(AuSPtr<Heap> heap, T *in, bool pinHeap = true)
{
return
std::shared_ptr<T>(in,
[=](T *delt)
{
heap->Free(delt);
});
auto handle = pinHeap ? heap : {};
auto ptr = heap.get(); // so long as in is a valid pointer within the heap, this is fine
return std::shared_ptr<T>(in,
[handle, ptr](T *delt)
{
ptr->Free(delt);
});
}
private:
virtual AuSPtr<Heap> GetSelfReference() = 0;
virtual AU_ALLOC void *_ZAlloc(Types::size_t length) = 0;
virtual AU_ALLOC void *_ZAlloc(Types::size_t length, Types::size_t align) = 0;
virtual AU_ALLOC void *_FAlloc(Types::size_t length) = 0;
@ -133,6 +147,10 @@ namespace Aurora::Memory
/**
Allocates Fize amount of memory
NOTE -> Heaps are guaranteed to outlive its' allocations; heap are the one object that own themselves
Destructions are mere suggestions, however, requesting termination before a heap has released all of its memory will result in a telemetry mayday
@return a heap backed by allocated memory
*/
AUKN_SHARED_API(AllocHeap, Heap, AuUInt size);

View File

@ -62,6 +62,11 @@ namespace Aurora::Memory
{
return Aurora::Memory::_Free(buffer);
}
AuSPtr<Heap> GetSelfReference() override
{
return {};
}
};
static DefaultHeap gDefaultAllocation;

View File

@ -48,7 +48,7 @@ namespace Aurora::Memory
#endif
}
class InternalHeap : public Heap
class InternalHeap : public Heap, std::enable_shared_from_this<InternalHeap>
{
public:
InternalHeap() : base_(nullptr), mutex_(nullptr), heap_(nullptr), count_(0)
@ -82,6 +82,7 @@ namespace Aurora::Memory
void *_FRealloc(void *buffer, Types::size_t length) override;
void *_FRealloc(void *buffer, Types::size_t length, Types::size_t align) override;
void _Free(void *buffer) override;
AuSPtr<Heap> GetSelfReference() override;
void TryRelease();
void RequestTermination();
@ -241,6 +242,18 @@ namespace Aurora::Memory
}
}
AuSPtr<Heap> InternalHeap::GetSelfReference()
{
try
{
return shared_from_this();
}
catch (...)
{
return {};
}
}
AUKN_SYM Heap *AllocHeapNew(AuUInt size)
{
auto heap = _new InternalHeap();