Add support for using custom memory allocator in lambda bind to Function

This commit is contained in:
Wojtek Figat
2025-08-05 22:13:21 +02:00
parent a1a6d4738f
commit baf0cfce8e

View File

@@ -62,7 +62,7 @@ private:
struct Lambda
{
int64 Refs;
void (*Dtor)(void*);
void (*Dtor)(void* callee, Lambda* lambda);
};
void* _callee;
@@ -78,8 +78,7 @@ private:
{
if (Platform::InterlockedDecrement(&_lambda->Refs) == 0)
{
((Lambda*)_lambda)->Dtor(_callee);
Allocator::Free(_lambda);
_lambda->Dtor(_callee, _lambda);
}
}
@@ -189,9 +188,10 @@ public:
LambdaDtor();
_lambda = (Lambda*)Allocator::Allocate(sizeof(Lambda) + sizeof(T));
_lambda->Refs = 1;
_lambda->Dtor = [](void* callee) -> void
_lambda->Dtor = [](void* callee, Lambda* lambda) -> void
{
static_cast<T*>(callee)->~T();
Allocator::Free(lambda);
};
_function = [](void* callee, Params... params) -> ReturnType
{
@@ -201,6 +201,45 @@ public:
new(_callee) T(lambda);
}
/// <summary>
/// Binds a lambda with a custom memory allocator.
/// </summary>
/// <param name="tag">The custom allocation tag.</param>
/// <param name="lambda">The lambda.</param>
template<typename AllocationType, typename T>
void Bind(typename AllocationType::Tag tag, const T& lambda)
{
if (_lambda)
LambdaDtor();
using AllocationData = typename AllocationType::template Data<byte>;
static_assert(AllocationType::HasSwap, "Function lambda binding supports only custom allocators with swap operation.");
// Allocate lambda (using temp data)
AllocationData tempAlloc(tag);
tempAlloc.Allocate(sizeof(Lambda) + sizeof(AllocationData) + sizeof(T));
// Move temp data into the one allocated
AllocationData* dataAlloc = (AllocationData*)(tempAlloc.Get() + sizeof(Lambda));
new(dataAlloc) AllocationData();
dataAlloc->Swap(tempAlloc);
// Initialize lambda
_lambda = (Lambda*)dataAlloc->Get();
_lambda->Refs = 1;
_lambda->Dtor = [](void* callee, Lambda* lambda) -> void
{
static_cast<T*>(callee)->~T();
AllocationData* dataAlloc = (AllocationData*)((byte*)lambda + sizeof(Lambda));
dataAlloc->Free();
};
_function = [](void* callee, Params... params) -> ReturnType
{
return (*static_cast<T*>(callee))(Forward<Params>(params)...);
};
_callee = (byte*)_lambda + sizeof(AllocationData) + sizeof(Lambda);
new(_callee) T(lambda);
}
/// <summary>
/// Unbinds the function.
/// </summary>