From 23a8f1ed5b24c05ac203fc7f30a03f7fc52c0cbd Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Thu, 28 Mar 2024 14:40:07 +0100 Subject: C++ migration: Linda is a proper class with overloaded operator new/delete --- src/deep.cpp | 21 +++++++++++---------- src/keeper.cpp | 6 +++--- src/keeper.h | 8 ++++---- src/linda.cpp | 28 ++++++++++++++++------------ 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/deep.cpp b/src/deep.cpp index 74ecfb8..652b19d 100644 --- a/src/deep.cpp +++ b/src/deep.cpp @@ -32,21 +32,22 @@ THE SOFTWARE. =============================================================================== */ +#include "compat.h" +#include "deep.h" +#include "tools.h" +#include "uniquekey.h" +#include "universe.h" + +#include +#include +#include #include -#include #include -#include #include #if !defined(__APPLE__) #include #endif -#include "compat.h" -#include "deep.h" -#include "tools.h" -#include "universe.h" -#include "uniquekey.h" - /*-- Metatable copying --*/ /*---=== Deep userdata ===---*/ @@ -227,7 +228,7 @@ char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, Lookup prelude->m_refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data // Get/create metatable for 'idfunc' (in this state) - lua_pushlightuserdata( L, (void*)(ptrdiff_t)(prelude->idfunc)); // DPC proxy idfunc + lua_pushlightuserdata( L, std::bit_cast(prelude->idfunc)); // DPC proxy idfunc get_deep_lookup( L); // DPC proxy metatable? if( lua_isnil( L, -1)) // // No metatable yet. @@ -269,7 +270,7 @@ char const* push_deep_proxy(lua_State* L, DeepPrelude* prelude, int nuv_, Lookup // Memorize for later rounds lua_pushvalue( L, -1); // DPC proxy metatable metatable - lua_pushlightuserdata( L, (void*)(ptrdiff_t)(prelude->idfunc)); // DPC proxy metatable metatable idfunc + lua_pushlightuserdata( L, std::bit_cast(prelude->idfunc)); // DPC proxy metatable metatable idfunc set_deep_lookup( L); // DPC proxy metatable // 2 - cause the target state to require the module that exported the idfunc diff --git a/src/keeper.cpp b/src/keeper.cpp index 1919a68..9c41b1c 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp @@ -207,7 +207,7 @@ static void push_table(lua_State* L, int idx_) // ################################################################################################## -int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_) +int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, uintptr_t magic_) { Keeper* const K = which_keeper( U->keepers, magic_); lua_State* const KL = K ? K->L : nullptr; @@ -731,7 +731,7 @@ void init_keepers(Universe* U, lua_State* L) // ################################################################################################## // should be called only when inside a keeper_acquire/keeper_release pair (see linda_protected_call) -Keeper* which_keeper(Keepers* keepers_, ptrdiff_t magic_) +Keeper* which_keeper(Keepers* keepers_, uintptr_t magic_) { int const nbKeepers{ keepers_->nb_keepers }; unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); @@ -740,7 +740,7 @@ Keeper* which_keeper(Keepers* keepers_, ptrdiff_t magic_) // ################################################################################################## -Keeper* keeper_acquire(Keepers* keepers_, ptrdiff_t magic_) +Keeper* keeper_acquire(Keepers* keepers_, uintptr_t magic_) { int const nbKeepers{ keepers_->nb_keepers }; // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) diff --git a/src/keeper.h b/src/keeper.h index 5f52fa0..fc0aa6b 100644 --- a/src/keeper.h +++ b/src/keeper.h @@ -28,18 +28,18 @@ struct Keepers Keeper keeper_array[1]; }; -static constexpr ptrdiff_t KEEPER_MAGIC_SHIFT{ 3 }; +static constexpr uintptr_t KEEPER_MAGIC_SHIFT{ 3 }; // crc64/we of string "NIL_SENTINEL" generated at http://www.nitrxgen.net/hashgen/ static constexpr UniqueKey NIL_SENTINEL{ 0x7eaafa003a1d11a1ull }; void init_keepers(Universe* U, lua_State* L); void close_keepers(Universe* U); -Keeper* which_keeper(Keepers* keepers_, ptrdiff_t magic_); -Keeper* keeper_acquire(Keepers* keepers_, ptrdiff_t magic_); +Keeper* which_keeper(Keepers* keepers_, uintptr_t magic_); +Keeper* keeper_acquire(Keepers* keepers_, uintptr_t magic_); void keeper_release(Keeper* K); void keeper_toggle_nil_sentinels(lua_State* L, int val_i_, LookupMode const mode_); -int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_); +int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, uintptr_t magic_); using keeper_api_t = lua_CFunction; #define KEEPER_API(_op) keepercall_##_op diff --git a/src/linda.cpp b/src/linda.cpp index e1633b0..dc5864b 100644 --- a/src/linda.cpp +++ b/src/linda.cpp @@ -50,7 +50,7 @@ THE SOFTWARE. * Actual data is kept within a keeper state, which is hashed by the 'Linda' * pointer (which is same to all userdatas pointing to it). */ -struct Linda : public DeepPrelude // Deep userdata MUST start with this header +class Linda : public DeepPrelude // Deep userdata MUST start with this header { private: @@ -61,19 +61,28 @@ struct Linda : public DeepPrelude // Deep userdata MUST start with this header size_t len{ 0 }; char* name{ nullptr }; }; + // depending on the name length, it is either embedded inside the Linda, or allocated separately + std::variant m_name; public: SIGNAL_T read_happened; SIGNAL_T write_happened; Universe* const U; // the universe this linda belongs to - ptrdiff_t const group; // a group to control keeper allocation between lindas + uintptr_t const group; // a group to control keeper allocation between lindas CancelRequest simulate_cancel{ CancelRequest::None }; - std::variant m_name; public: - Linda(Universe* U_, ptrdiff_t group_, char const* name_, size_t len_) + // a fifo full userdata has one uservalue, the table that holds the actual fifo contents + static void* operator new(size_t size_, Universe* U_) noexcept { return U_->internal_allocator.alloc(size_); } + // always embedded somewhere else or "in-place constructed" as a full userdata + // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception + static void operator delete(void* p_, Universe* U_) { U_->internal_allocator.free(p_, sizeof(Linda)); } + // this one is for us, to make sure memory is freed by the correct allocator + static void operator delete(void* p_) { static_cast(p_)->U->internal_allocator.free(p_, sizeof(Linda)); } + + Linda(Universe* U_, uintptr_t group_, char const* name_, size_t len_) : U{ U_ } , group{ group_ << KEEPER_MAGIC_SHIFT } { @@ -122,7 +131,7 @@ struct Linda : public DeepPrelude // Deep userdata MUST start with this header public: - ptrdiff_t hashSeed() const { return group ? group : std::bit_cast(this); } + uintptr_t hashSeed() const { return group ? group : std::bit_cast(this); } char const* getName() const { @@ -887,11 +896,7 @@ static void* linda_id( lua_State* L, DeepOp op_) * just don't use L's allocF because we don't know which state will get the honor of GCing the linda */ Universe* const U{ universe_get(L) }; - Linda* s{ static_cast(U->internal_allocator.alloc(sizeof(Linda))) }; // terminating 0 is already included - if (s) - { - s->Linda::Linda(U, linda_group, linda_name, name_len); - } + Linda* s{ new (U) Linda{ U, linda_group, linda_name, name_len } }; return s; } @@ -909,8 +914,7 @@ static void* linda_id( lua_State* L, DeepOp op_) } keeper_release( K); - linda->Linda::~Linda(); - linda->U->internal_allocator.free(linda, sizeof(Linda)); + delete linda; // operator delete overload ensures things go as expected return nullptr; } -- cgit v1.2.3-55-g6feb