From fdc5e8760fb7ac0af8e7ebb98a2076db15e31082 Mon Sep 17 00:00:00 2001 From: aura Date: Mon, 16 Mar 2026 10:15:01 +0100 Subject: giga refactor, fix ALL the leaks --- src/util/callback.h | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/util/callback.h (limited to 'src/util/callback.h') diff --git a/src/util/callback.h b/src/util/callback.h new file mode 100644 index 0000000..df93b59 --- /dev/null +++ b/src/util/callback.h @@ -0,0 +1,88 @@ +#pragma once +#include "typedef.h" + +template +struct FN; + +template +struct FN { + // voodoo + template struct __strip_ref { using type = T; }; + template struct __strip_ref { using type = T; }; + template struct __strip_ref { using type = T; }; + template struct __strip_ref { using type = R(*)(A...); }; + template struct __strip_ref { using type = R(*)(A...); }; + + void* data; + U32 size; + RET( *invoke )( void*, ARGS... ); + void( *destroy )( void* ); + void*( *clone )( void* ); + + template + FN( F&& f ) { + using __stripped = typename __strip_ref::type; + data = new __stripped( static_cast(f) ); + size = sizeof( __stripped ); + invoke = pfn( void* d, ARGS... args ) -> RET { + return ( *(__stripped*)d )( args... ); + }; + destroy = pfn( void* d ) { + delete (__stripped*)d; + }; + clone = pfn( void* data ) { + return (void*)new __stripped( *(__stripped*)data ); + }; + } + + template <> + FN( int&& ) : data( 0 ), invoke( 0 ), destroy( 0 ) {} + FN() : data( 0 ), invoke( 0 ), destroy( 0 ) {} + + FN( FN&& other ) : data( other.data ), invoke( other.invoke ), destroy( other.destroy ) { + other.data = 0; + other.invoke = 0; + other.destroy = 0; + } + + FN& operator=( FN&& other ) { + if( this == &other ) return *this; + if( destroy ) destroy( data ); + data = other.data; + invoke = other.invoke; + destroy = other.destroy; + other.data = 0; + other.invoke = 0; + other.destroy = 0; + return *this; + } + + FN( const FN& other ) { + *this = other; + }; + + FN& operator=( const FN& other ) { + if( !other.data ) { + data = 0; + invoke = 0; + destroy = 0; + size = 0; + return *this; + } + + size = other.size; + data = other.clone( other.data ); + invoke = other.invoke; + destroy = other.destroy; + clone = other.clone; + return *this; + } + + ~FN() { if( destroy ) destroy( data ); } + operator bool() const { return !!invoke; } + + RET operator()( ARGS... args ) const { + return invoke( data, args... ); + } + +}; -- cgit v1.2.3