From f214d35df5f09e7026dafd8553e83cc6ea21cbde Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Tue, 26 Mar 2024 17:46:00 +0100 Subject: C++ migration: templated lua_touserdata --- src/deep.cpp | 14 ++++++-------- src/keeper.cpp | 32 ++++++++++++++++++++------------ src/lanes.cpp | 6 +++--- src/lanes_private.h | 2 +- src/linda.cpp | 2 +- src/macros_and_utils.h | 7 +++++++ src/state.cpp | 2 +- src/universe.cpp | 2 +- src/universe.h | 2 +- 9 files changed, 41 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/deep.cpp b/src/deep.cpp index dd682e4..f091d4d 100644 --- a/src/deep.cpp +++ b/src/deep.cpp @@ -113,7 +113,7 @@ static inline luaG_IdFunction* get_idfunc( lua_State* L, int index, LookupMode m // when looking inside a keeper, we are 100% sure the object is a deep userdata if( mode_ == eLM_FromKeeper) { - DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, index); + DeepPrelude** const proxy{ lua_touserdata(L, index) }; // we can (and must) cast and fetch the internally stored idfunc return (*proxy)->idfunc; } @@ -133,7 +133,7 @@ static inline luaG_IdFunction* get_idfunc( lua_State* L, int index, LookupMode m // replace metatable with the idfunc pointer, if it is actually a deep userdata get_deep_lookup( L); // deep ... idfunc|nil - luaG_IdFunction* const ret{ static_cast(lua_touserdata(L, -1)) }; // nullptr if not a userdata + luaG_IdFunction* const ret{ lua_touserdata(L, -1) }; // nullptr if not a userdata lua_pop( L, 1); STACK_CHECK( L, 0); return ret; @@ -161,7 +161,7 @@ void free_deep_prelude( lua_State* L, DeepPrelude* prelude_) */ static int deep_userdata_gc( lua_State* L) { - DeepPrelude** proxy = (DeepPrelude**) lua_touserdata( L, 1); + DeepPrelude** const proxy{ lua_touserdata(L, 1) }; DeepPrelude* p = *proxy; // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded @@ -418,17 +418,15 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction* idfunc, int nuv_) */ void* luaG_todeep( lua_State* L, luaG_IdFunction* idfunc, int index) { - DeepPrelude** proxy; - STACK_CHECK_START_REL(L, 0); // ensure it is actually a deep userdata if( get_idfunc( L, index, eLM_LaneBody) != idfunc) { return nullptr; // no metatable, or wrong kind } + STACK_CHECK(L, 0); - proxy = (DeepPrelude**) lua_touserdata( L, index); - STACK_CHECK( L, 0); + DeepPrelude** const proxy{ lua_touserdata(L, index) }; return *proxy; } @@ -464,7 +462,7 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L lua_pop( L, 1); // ... u [uv]* STACK_CHECK( L, nuv); - errmsg = push_deep_proxy(L2, *(DeepPrelude**) lua_touserdata( L, i), nuv, mode_); // u + errmsg = push_deep_proxy(L2, *lua_touserdata(L, i), nuv, mode_); // u // transfer all uservalues of the source in the destination { diff --git a/src/keeper.cpp b/src/keeper.cpp index 88bd4ff..35b5ea8 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp @@ -52,11 +52,18 @@ // Keeper implementation // ################################################################################### -struct keeper_fifo +class keeper_fifo { + public: + int first{ 1 }; int count{ 0 }; int limit{ -1 }; + + static void* operator new(size_t size_, lua_State* L) noexcept { return lua_newuserdatauv(L, size_, 1); } + // 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_, lua_State* L){ ASSERT_L(!"should never be called") }; }; static constexpr int CONTENTS_TABLE{ 1 }; @@ -66,7 +73,7 @@ static constexpr int CONTENTS_TABLE{ 1 }; // replaces the fifo ud by its uservalue on the stack static keeper_fifo* prepare_fifo_access(lua_State* L, int idx_) { - keeper_fifo* const fifo{ static_cast(lua_touserdata(L, idx_)) }; + keeper_fifo* const fifo{ lua_touserdata(L, idx_) }; if (fifo != nullptr) { idx_ = lua_absindex(L, idx_); @@ -84,13 +91,14 @@ static keeper_fifo* prepare_fifo_access(lua_State* L, int idx_) // out: { first = 1, count = 0, limit = -1} static void fifo_new(lua_State* L) { - keeper_fifo* fifo; STACK_GROW(L, 2); + STACK_CHECK_START_REL(L, 0); // a fifo full userdata has one uservalue, the table that holds the actual fifo contents - fifo = (keeper_fifo*) lua_newuserdatauv(L, sizeof(keeper_fifo), 1); - fifo->keeper_fifo::keeper_fifo(); + [[maybe_unused]] keeper_fifo* const fifo{ new (L) keeper_fifo{} }; + STACK_CHECK(L, 1); lua_newtable(L); lua_setiuservalue(L, -2, CONTENTS_TABLE); + STACK_CHECK(L, 1); } // ################################################################################################## @@ -163,13 +171,13 @@ static void fifo_pop( lua_State* L, keeper_fifo* fifo_, int count_) // ################################################################################################## -// in: linda_ud expected at *absolute* stack slot idx +// in: linda_ud expected at stack slot idx // out: fifos[ud] // crc64/we of string "FIFOS_KEY" generated at http://www.nitrxgen.net/hashgen/ static constexpr UniqueKey FIFOS_KEY{ 0xdce50bbc351cd465ull }; static void push_table(lua_State* L, int idx_) { - STACK_GROW(L, 4); + STACK_GROW(L, 5); STACK_CHECK_START_REL(L, 0); idx_ = lua_absindex(L, idx_); FIFOS_KEY.query_registry(L); // ud fifos @@ -276,7 +284,7 @@ int keepercall_send(lua_State* L) lua_rawset(L, -4); // ud key ... fifos fifo } lua_remove(L, -2); // ud key ... fifo - keeper_fifo* fifo{ static_cast(lua_touserdata(L, -1)) }; + keeper_fifo* fifo{ lua_touserdata(L, -1) }; if( fifo->limit >= 0 && fifo->count + n > fifo->limit) { lua_settop(L, 0); // @@ -374,12 +382,12 @@ int keepercall_limit(lua_State* L) lua_pop(L, 1); // fifos key lua_pushvalue(L, -1); // fifos key key lua_rawget(L, -3); // fifos key fifo|nil - keeper_fifo* fifo{ static_cast(lua_touserdata(L, -1)) }; + keeper_fifo* fifo{ lua_touserdata(L, -1) }; if (fifo == nullptr) { // fifos key nil lua_pop(L, 1); // fifos key fifo_new(L); // fifos key fifo - fifo = static_cast(lua_touserdata(L, -1)); + fifo = lua_touserdata(L, -1); lua_rawset(L, -3); // fifos } // remove any clutter on the stack @@ -418,7 +426,7 @@ int keepercall_set(lua_State* L) lua_pushvalue(L, -1); // fifos key key lua_rawget(L, 1); // fifos key fifo|nil // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! - keeper_fifo* const fifo{ static_cast(lua_touserdata(L, -1)) }; + keeper_fifo* const fifo{ lua_touserdata(L, -1) }; if (fifo != nullptr) // might be nullptr if we set a nonexistent key to nil { // fifos key fifo if (fifo->limit < 0) // fifo limit value is the default (unlimited): we can totally remove it @@ -444,7 +452,7 @@ int keepercall_set(lua_State* L) int const count{ lua_gettop(L) - 2 }; // number of items we want to store lua_pushvalue(L, 2); // fifos key [val [, ...]] key lua_rawget(L, 1); // fifos key [val [, ...]] fifo|nil - keeper_fifo* fifo = static_cast(lua_touserdata( L, -1)); + keeper_fifo* fifo{ lua_touserdata(L, -1) }; if( fifo == nullptr) // can be nullptr if we store a value at a new key { // fifos key [val [, ...]] nil // no need to wake writers in that case, because a writer can't wait on an inexistent key diff --git a/src/lanes.cpp b/src/lanes.cpp index 5945a1a..6b3542b 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp @@ -442,7 +442,7 @@ static bool selfdestruct_remove( Lane* s) */ static int selfdestruct_gc( lua_State* L) { - Universe* U = (Universe*) lua_touserdata( L, 1); + Universe* const U{ lua_touserdata(L, 1) }; while( U->selfdestruct_first != SELFDESTRUCT_END) // true at most once! { @@ -781,7 +781,7 @@ LUAG_FUNC( set_debug_threadname) // fnv164 of string "debug_threadname" generated at https://www.pelock.com/products/hash-calculator constexpr UniqueKey hidden_regkey{ 0x79C0669AAAE04440ull }; // C s_lane structure is a light userdata upvalue - Lane* s = (Lane*) lua_touserdata( L, lua_upvalueindex( 1)); + Lane* const s{ lua_touserdata(L, lua_upvalueindex(1)) }; luaL_checktype( L, -1, LUA_TSTRING); // "name" lua_settop( L, 1); STACK_CHECK_START_ABS( L, 1); @@ -1887,7 +1887,7 @@ LUAG_FUNC( configure) STACK_CHECK( L, 2); // Proxy userdata contents is only a 'DeepPrelude*' pointer - U->timer_deep = *(DeepPrelude**) lua_touserdata( L, -1); + U->timer_deep = *lua_touserdata(L, -1); // increment refcount so that this linda remains alive as long as the universe exists. U->timer_deep->m_refcount.fetch_add(1, std::memory_order_relaxed); lua_pop( L, 1); // settings diff --git a/src/lanes_private.h b/src/lanes_private.h index b8d26d3..839a51f 100644 --- a/src/lanes_private.h +++ b/src/lanes_private.h @@ -83,7 +83,7 @@ static inline Lane* get_lane_from_registry( lua_State* L) STACK_GROW( L, 1); STACK_CHECK_START_REL(L, 0); CANCEL_TEST_KEY.query_registry(L); - Lane* const s = static_cast(lua_touserdata(L, -1)); // lightuserdata (true 's_lane' pointer) / nil + Lane* const s{ lua_touserdata(L, -1) }; // lightuserdata (true 's_lane' pointer) / nil lua_pop( L, 1); STACK_CHECK( L, 0); return s; diff --git a/src/linda.cpp b/src/linda.cpp index eb2349e..7e346d8 100644 --- a/src/linda.cpp +++ b/src/linda.cpp @@ -808,7 +808,7 @@ static void* linda_id( lua_State* L, DeepOp op_) case eDO_delete: { - struct s_Linda* linda = (struct s_Linda*) lua_touserdata( L, 1); + struct s_Linda* const linda{ lua_touserdata(L, 1) }; ASSERT_L( linda); // Clean associated structures in the keeper state. diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index c549d72..370cbed 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h @@ -124,3 +124,10 @@ inline void STACK_GROW(lua_State* L, int n_) } #define LUAG_FUNC( func_name) int LG_##func_name( lua_State* L) + +// a small helper to extract a userdata pointer from the stack +template +T* lua_touserdata(lua_State* L, int index_) +{ + return static_cast(lua_touserdata(L, index_)); +} diff --git a/src/state.cpp b/src/state.cpp index 7bdaec9..b46a145 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -259,7 +259,7 @@ lua_State* create_state( Universe* U, lua_State* from_) lua_pushcclosure( from_, U->provide_allocator, 0); lua_call( from_, 0, 1); { - AllocatorDefinition* const def = (AllocatorDefinition*) lua_touserdata( from_, -1); + AllocatorDefinition* const def{ lua_touserdata(from_, -1) }; L = lua_newstate( def->m_allocF, def->m_allocUD); } lua_pop( from_, 1); diff --git a/src/universe.cpp b/src/universe.cpp index 4dd956d..095f000 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -67,7 +67,7 @@ Universe* universe_get(lua_State* L) STACK_GROW(L, 2); STACK_CHECK_START_REL(L, 0); UNIVERSE_REGKEY.query_registry(L); - Universe* const universe = static_cast(lua_touserdata(L, -1)); // nullptr if nil + Universe* const universe{ lua_touserdata(L, -1) }; // nullptr if nil lua_pop(L, 1); STACK_CHECK(L, 0); return universe; diff --git a/src/universe.h b/src/universe.h index bb3ebdd..04c92ca 100644 --- a/src/universe.h +++ b/src/universe.h @@ -142,7 +142,7 @@ struct Universe // Initialized by 'init_once_LOCKED()': the deep userdata Linda object // used for timers (each lane will get a proxy to this) - volatile DeepPrelude* timer_deep{ nullptr }; // = nullptr + DeepPrelude* timer_deep{ nullptr }; #if HAVE_LANE_TRACKING() std::mutex tracking_cs; -- cgit v1.2.3-55-g6feb