diff options
| author | aura <nw@moneybot.cc> | 2026-03-16 10:57:36 +0100 |
|---|---|---|
| committer | aura <nw@moneybot.cc> | 2026-03-16 10:57:36 +0100 |
| commit | b71bb14c7dec546304e3396d7040d88c6c86a3a7 (patch) | |
| tree | e1bee4e513b7df5647cbfacbe10cab4ebbc5cfc8 /src | |
| parent | fdc5e8760fb7ac0af8e7ebb98a2076db15e31082 (diff) | |
decreaso allocs for fn class
Diffstat (limited to 'src')
| -rw-r--r-- | src/util/callback.h | 90 |
1 files changed, 43 insertions, 47 deletions
diff --git a/src/util/callback.h b/src/util/callback.h index df93b59..a2c9477 100644 --- a/src/util/callback.h +++ b/src/util/callback.h @@ -3,86 +3,82 @@ template <typename T> struct FN; - +// voodoo template <typename RET, typename... ARGS> struct FN<RET(ARGS...)> { - // voodoo template <typename T> struct __strip_ref { using type = T; }; template <typename T> struct __strip_ref<T&> { using type = T; }; template <typename T> struct __strip_ref<T&&> { using type = T; }; template <typename R, typename... A> struct __strip_ref<R(A...)> { using type = R(*)(A...); }; template <typename R, typename... A> struct __strip_ref<R(&)(A...)> { using type = R(*)(A...); }; + static const unsigned int BUF_SIZE = 32; + + alignas(8) char buf[BUF_SIZE]; void* data; - U32 size; RET( *invoke )( void*, ARGS... ); void( *destroy )( void* ); - void*( *clone )( void* ); + void*( *clone )( void*, char* ); template <typename F> - FN( F&& f ) { + FN(F&& f) { using __stripped = typename __strip_ref<F>::type; - data = new __stripped( static_cast<F&&>(f) ); - size = sizeof( __stripped ); + + if constexpr( sizeof(__stripped) <= BUF_SIZE ) { + new (buf) __stripped( f ); + data = buf; + destroy = pfn( void* d ) { + ( (__stripped*)d )->~__stripped(); + }; + clone = pfn( void* d, char* dst ) -> void* { + new (dst) __stripped( *(__stripped*)d ); + return dst; + }; + } else { + data = new __stripped( f ); + destroy = pfn( void* d ) { + delete (__stripped*)d; + }; + clone = pfn( void* d, char* dst ) -> void* { + return new __stripped( *(__stripped*)d ); + }; + } + 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( I32&& ) : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {} + FN( U32&& ) : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {} + FN() : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {} - FN& operator=( const FN& other ) { + FN( const FN& other ) : invoke( other.invoke ), destroy( other.destroy ), clone( other.clone ) { if( !other.data ) { data = 0; - invoke = 0; - destroy = 0; - size = 0; - return *this; + return; } - size = other.size; - data = other.clone( other.data ); + data = other.clone( other.data, buf ); + } + + FN& operator=( const FN& other ) { + if( this == &other ) return *this; + if( destroy && data ) destroy( data ); invoke = other.invoke; destroy = other.destroy; clone = other.clone; + data = other.data ? other.clone( other.data, buf ) : 0; return *this; } - ~FN() { if( destroy ) destroy( data ); } - operator bool() const { return !!invoke; } + ~FN() { + if( destroy && data ) destroy( data ); + } RET operator()( ARGS... args ) const { return invoke( data, args... ); } + operator bool() const { return !!invoke; } }; |
