From a65a84cfad4eae38e5e84b1ab11f60a62833f287 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Fri, 31 May 2024 11:40:28 +0200 Subject: Improved multi-keeper tests --- src/deep.cpp | 9 +++++---- src/lanes.cpp | 2 +- src/lanes.lua | 37 +++++++++++++++++++------------------ 3 files changed, 25 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/deep.cpp b/src/deep.cpp index f5716bf..34cc4b4 100644 --- a/src/deep.cpp +++ b/src/deep.cpp @@ -78,9 +78,9 @@ namespace { // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded // in that case, we are not multithreaded and locking isn't necessary anyway - bool const isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 }; + bool const _isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 }; - if (isLastRef) { + if (_isLastRef) { // retrieve wrapped __gc, if any lua_pushvalue(L_, lua_upvalueindex(1)); // L_: self __gc? if (!lua_isnil(L_, -1)) { @@ -123,6 +123,7 @@ namespace { // ################################################################################################# // ################################################################################################# +// NEVER call deleteDeepObjectInternal by itself, ALWAYS go through DeleteDeepObject() void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_) { STACK_CHECK_START_REL(L_, 0); @@ -310,7 +311,7 @@ int DeepFactory::pushDeepUserdata(DestState const L_, int const nuv_) const if (_prelude->magic != kDeepVersion) { // just in case, don't leak the newly allocated deep userdata object - deleteDeepObjectInternal(L_, _prelude); + DeleteDeepObject(L_, _prelude); raise_luaL_error(L_, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation"); } @@ -319,7 +320,7 @@ int DeepFactory::pushDeepUserdata(DestState const L_, int const nuv_) const if (lua_gettop(L_) - _oldtop != 0) { // just in case, don't leak the newly allocated deep userdata object - deleteDeepObjectInternal(L_, _prelude); + DeleteDeepObject(L_, _prelude); raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); } diff --git a/src/lanes.cpp b/src/lanes.cpp index 4b4f9a8..41450f3 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp @@ -664,7 +664,7 @@ LUAG_FUNC(configure) STACK_CHECK(L_, 2); DeepFactory::PushDeepProxy(DestState{ L_ }, _U->timerLinda, 0, LookupMode::LaneBody, L_); // L_: settings M timerLinda - lua_setfield(L_, -2, "timer_gateway"); // L_: settings M + lua_setfield(L_, -2, "timerLinda"); // L_: settings M STACK_CHECK(L_, 2); // prepare the metatable for threads diff --git a/src/lanes.lua b/src/lanes.lua index 1c36b46..d5a04e5 100644 --- a/src/lanes.lua +++ b/src/lanes.lua @@ -376,8 +376,9 @@ local timer = function() error "timers are not active" end local timers = timer local timer_lane = nil --- timer_gateway should always exist, even when the settings disable the timers -local timer_gateway +-- timerLinda should always exist, even when the settings disable the timers +-- is upvalue of timer stuff and lanes.sleep() +local timerLinda local TGW_KEY = "(timer control)" -- the key does not matter, a 'weird' key may help debugging local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)" @@ -387,7 +388,7 @@ local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)" local configure_timers = function() -- On first 'require "lanes"', a timer lane is spawned that will maintain -- timer tables and sleep in between the timer events. All interaction with - -- the timer lane happens via a 'timer_gateway' Linda, which is common to + -- the timer lane happens via a 'timerLinda' Linda, which is common to -- all that 'require "lanes"'. -- -- Linda protocol to timer lane: @@ -399,8 +400,8 @@ local configure_timers = function() -- Timer lane; initialize only on the first 'require "lanes"' instance (which naturally has 'table' always declared) local first_time_key = "first time" - local first_time = timer_gateway:get(first_time_key) == nil - timer_gateway:set(first_time_key, true) + local first_time = timerLinda:get(first_time_key) == nil + timerLinda:set(first_time_key, true) if first_time then assert(type(now_secs) == "function") @@ -552,7 +553,7 @@ local configure_timers = function() return next_wakeup -- may be 'nil' end -- check_timers() - local timer_gateway_batched = timer_gateway.batched + local timer_gateway_batched = timerLinda.batched set_finalizer(function(err, stk) if err and type(err) ~= "userdata" then error("LanesTimer error: "..tostring(err)) @@ -572,18 +573,18 @@ local configure_timers = function() secs = next_wakeup - now_secs() if secs < 0 then secs = 0 end end - local key, what = timer_gateway:receive(secs, TGW_KEY, TGW_QUERY) + local key, what = timerLinda:receive(secs, TGW_KEY, TGW_QUERY) if key == TGW_KEY then assert(getmetatable(what) == "Linda") -- 'what' should be a linda on which the client sets a timer - local _, key, wakeup_at, period = timer_gateway:receive(0, timer_gateway_batched, TGW_KEY, 3) + local _, key, wakeup_at, period = timerLinda:receive(0, timer_gateway_batched, TGW_KEY, 3) assert(key) set_timer(what, key, wakeup_at, period and period > 0 and period or nil) elseif key == TGW_QUERY then if what == "get_timers" then - timer_gateway:send(TGW_REPLY, get_timers()) + timerLinda:send(TGW_REPLY, get_timers()) else - timer_gateway:send(TGW_REPLY, "unknown query " .. what) + timerLinda:send(TGW_REPLY, "unknown query " .. what) end --elseif secs == nil then -- got no value while block-waiting? -- WR("timer lane: no linda, aborted?") @@ -610,7 +611,7 @@ local configure_timers = function() linda_:set(key_, now_secs()) if not period_ or period_ == 0.0 then - timer_gateway:send(TGW_KEY, linda_, key_, nil, nil ) -- clear the timer + timerLinda:send(TGW_KEY, linda_, key_, nil, nil ) -- clear the timer return -- nothing more to do end when_ = period_ @@ -620,7 +621,7 @@ local configure_timers = function() or (when_ and now_secs()+when_ or nil) -- queue to timer -- - timer_gateway:send(TGW_KEY, linda_, key_, wakeup_at, period_) + timerLinda:send(TGW_KEY, linda_, key_, wakeup_at, period_) end -- timer() ----- @@ -628,11 +629,11 @@ local configure_timers = function() -- -- PUBLIC LANES API timers = function() - timer_gateway:send(TGW_QUERY, "get_timers") - local _, r = timer_gateway:receive(TGW_REPLY) + timerLinda:send(TGW_QUERY, "get_timers") + local _, r = timerLinda:receive(TGW_REPLY) return r end -- timers() -end +end -- configure_timers() -- ################################################################################################# -- ###################################### lanes.sleep() ############################################ @@ -651,8 +652,8 @@ local sleep = function(seconds_) error("invalid duration " .. string_format("%q", tostring(seconds_))) end -- receive data on a channel no-one ever sends anything, thus blocking for the specified duration - return timer_gateway:receive(seconds_, "ac100de1-a696-4619-b2f0-a26de9d58ab8") -end -- sleep + return timerLinda:receive(seconds_, "ac100de1-a696-4619-b2f0-a26de9d58ab8") +end -- sleep() -- ################################################################################################# -- ##################################### lanes.genlock() ########################################### @@ -782,7 +783,7 @@ local configure = function(settings_) -- avoid pulling the whole core module as upvalue when cancel_error is enough -- these are locals declared above, that we need to set prior to calling configure_timers() cancel_error = assert(core.cancel_error) - timer_gateway = assert(core.timer_gateway) + timerLinda = assert(core.timerLinda) if settings.with_timers then configure_timers(settings) -- cgit v1.2.3-55-g6feb