aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-05-31 11:40:28 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-05-31 11:40:28 +0200
commita65a84cfad4eae38e5e84b1ab11f60a62833f287 (patch)
tree3d3b6cc88c188f2c34d3283e081316d6cc05ae83 /src
parent731556711e453a501f1d1d06a6013b8fbd53414e (diff)
downloadlanes-a65a84cfad4eae38e5e84b1ab11f60a62833f287.tar.gz
lanes-a65a84cfad4eae38e5e84b1ab11f60a62833f287.tar.bz2
lanes-a65a84cfad4eae38e5e84b1ab11f60a62833f287.zip
Improved multi-keeper tests
Diffstat (limited to 'src')
-rw-r--r--src/deep.cpp9
-rw-r--r--src/lanes.cpp2
-rw-r--r--src/lanes.lua37
3 files changed, 25 insertions, 23 deletions
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 {
78 78
79 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded 79 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded
80 // in that case, we are not multithreaded and locking isn't necessary anyway 80 // in that case, we are not multithreaded and locking isn't necessary anyway
81 bool const isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 }; 81 bool const _isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 };
82 82
83 if (isLastRef) { 83 if (_isLastRef) {
84 // retrieve wrapped __gc, if any 84 // retrieve wrapped __gc, if any
85 lua_pushvalue(L_, lua_upvalueindex(1)); // L_: self __gc? 85 lua_pushvalue(L_, lua_upvalueindex(1)); // L_: self __gc?
86 if (!lua_isnil(L_, -1)) { 86 if (!lua_isnil(L_, -1)) {
@@ -123,6 +123,7 @@ namespace {
123// ################################################################################################# 123// #################################################################################################
124// ################################################################################################# 124// #################################################################################################
125 125
126// NEVER call deleteDeepObjectInternal by itself, ALWAYS go through DeleteDeepObject()
126void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_) 127void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_)
127{ 128{
128 STACK_CHECK_START_REL(L_, 0); 129 STACK_CHECK_START_REL(L_, 0);
@@ -310,7 +311,7 @@ int DeepFactory::pushDeepUserdata(DestState const L_, int const nuv_) const
310 311
311 if (_prelude->magic != kDeepVersion) { 312 if (_prelude->magic != kDeepVersion) {
312 // just in case, don't leak the newly allocated deep userdata object 313 // just in case, don't leak the newly allocated deep userdata object
313 deleteDeepObjectInternal(L_, _prelude); 314 DeleteDeepObject(L_, _prelude);
314 raise_luaL_error(L_, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation"); 315 raise_luaL_error(L_, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation");
315 } 316 }
316 317
@@ -319,7 +320,7 @@ int DeepFactory::pushDeepUserdata(DestState const L_, int const nuv_) const
319 320
320 if (lua_gettop(L_) - _oldtop != 0) { 321 if (lua_gettop(L_) - _oldtop != 0) {
321 // just in case, don't leak the newly allocated deep userdata object 322 // just in case, don't leak the newly allocated deep userdata object
322 deleteDeepObjectInternal(L_, _prelude); 323 DeleteDeepObject(L_, _prelude);
323 raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); 324 raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack");
324 } 325 }
325 326
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)
664 664
665 STACK_CHECK(L_, 2); 665 STACK_CHECK(L_, 2);
666 DeepFactory::PushDeepProxy(DestState{ L_ }, _U->timerLinda, 0, LookupMode::LaneBody, L_); // L_: settings M timerLinda 666 DeepFactory::PushDeepProxy(DestState{ L_ }, _U->timerLinda, 0, LookupMode::LaneBody, L_); // L_: settings M timerLinda
667 lua_setfield(L_, -2, "timer_gateway"); // L_: settings M 667 lua_setfield(L_, -2, "timerLinda"); // L_: settings M
668 STACK_CHECK(L_, 2); 668 STACK_CHECK(L_, 2);
669 669
670 // prepare the metatable for threads 670 // 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
376local timers = timer 376local timers = timer
377local timer_lane = nil 377local timer_lane = nil
378 378
379-- timer_gateway should always exist, even when the settings disable the timers 379-- timerLinda should always exist, even when the settings disable the timers
380local timer_gateway 380-- is upvalue of timer stuff and lanes.sleep()
381local timerLinda
381 382
382local TGW_KEY = "(timer control)" -- the key does not matter, a 'weird' key may help debugging 383local TGW_KEY = "(timer control)" -- the key does not matter, a 'weird' key may help debugging
383local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)" 384local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)"
@@ -387,7 +388,7 @@ local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)"
387local configure_timers = function() 388local configure_timers = function()
388 -- On first 'require "lanes"', a timer lane is spawned that will maintain 389 -- On first 'require "lanes"', a timer lane is spawned that will maintain
389 -- timer tables and sleep in between the timer events. All interaction with 390 -- timer tables and sleep in between the timer events. All interaction with
390 -- the timer lane happens via a 'timer_gateway' Linda, which is common to 391 -- the timer lane happens via a 'timerLinda' Linda, which is common to
391 -- all that 'require "lanes"'. 392 -- all that 'require "lanes"'.
392 -- 393 --
393 -- Linda protocol to timer lane: 394 -- Linda protocol to timer lane:
@@ -399,8 +400,8 @@ local configure_timers = function()
399 400
400 -- Timer lane; initialize only on the first 'require "lanes"' instance (which naturally has 'table' always declared) 401 -- Timer lane; initialize only on the first 'require "lanes"' instance (which naturally has 'table' always declared)
401 local first_time_key = "first time" 402 local first_time_key = "first time"
402 local first_time = timer_gateway:get(first_time_key) == nil 403 local first_time = timerLinda:get(first_time_key) == nil
403 timer_gateway:set(first_time_key, true) 404 timerLinda:set(first_time_key, true)
404 if first_time then 405 if first_time then
405 406
406 assert(type(now_secs) == "function") 407 assert(type(now_secs) == "function")
@@ -552,7 +553,7 @@ local configure_timers = function()
552 return next_wakeup -- may be 'nil' 553 return next_wakeup -- may be 'nil'
553 end -- check_timers() 554 end -- check_timers()
554 555
555 local timer_gateway_batched = timer_gateway.batched 556 local timer_gateway_batched = timerLinda.batched
556 set_finalizer(function(err, stk) 557 set_finalizer(function(err, stk)
557 if err and type(err) ~= "userdata" then 558 if err and type(err) ~= "userdata" then
558 error("LanesTimer error: "..tostring(err)) 559 error("LanesTimer error: "..tostring(err))
@@ -572,18 +573,18 @@ local configure_timers = function()
572 secs = next_wakeup - now_secs() 573 secs = next_wakeup - now_secs()
573 if secs < 0 then secs = 0 end 574 if secs < 0 then secs = 0 end
574 end 575 end
575 local key, what = timer_gateway:receive(secs, TGW_KEY, TGW_QUERY) 576 local key, what = timerLinda:receive(secs, TGW_KEY, TGW_QUERY)
576 577
577 if key == TGW_KEY then 578 if key == TGW_KEY then
578 assert(getmetatable(what) == "Linda") -- 'what' should be a linda on which the client sets a timer 579 assert(getmetatable(what) == "Linda") -- 'what' should be a linda on which the client sets a timer
579 local _, key, wakeup_at, period = timer_gateway:receive(0, timer_gateway_batched, TGW_KEY, 3) 580 local _, key, wakeup_at, period = timerLinda:receive(0, timer_gateway_batched, TGW_KEY, 3)
580 assert(key) 581 assert(key)
581 set_timer(what, key, wakeup_at, period and period > 0 and period or nil) 582 set_timer(what, key, wakeup_at, period and period > 0 and period or nil)
582 elseif key == TGW_QUERY then 583 elseif key == TGW_QUERY then
583 if what == "get_timers" then 584 if what == "get_timers" then
584 timer_gateway:send(TGW_REPLY, get_timers()) 585 timerLinda:send(TGW_REPLY, get_timers())
585 else 586 else
586 timer_gateway:send(TGW_REPLY, "unknown query " .. what) 587 timerLinda:send(TGW_REPLY, "unknown query " .. what)
587 end 588 end
588 --elseif secs == nil then -- got no value while block-waiting? 589 --elseif secs == nil then -- got no value while block-waiting?
589 -- WR("timer lane: no linda, aborted?") 590 -- WR("timer lane: no linda, aborted?")
@@ -610,7 +611,7 @@ local configure_timers = function()
610 linda_:set(key_, now_secs()) 611 linda_:set(key_, now_secs())
611 612
612 if not period_ or period_ == 0.0 then 613 if not period_ or period_ == 0.0 then
613 timer_gateway:send(TGW_KEY, linda_, key_, nil, nil ) -- clear the timer 614 timerLinda:send(TGW_KEY, linda_, key_, nil, nil ) -- clear the timer
614 return -- nothing more to do 615 return -- nothing more to do
615 end 616 end
616 when_ = period_ 617 when_ = period_
@@ -620,7 +621,7 @@ local configure_timers = function()
620 or (when_ and now_secs()+when_ or nil) 621 or (when_ and now_secs()+when_ or nil)
621 -- queue to timer 622 -- queue to timer
622 -- 623 --
623 timer_gateway:send(TGW_KEY, linda_, key_, wakeup_at, period_) 624 timerLinda:send(TGW_KEY, linda_, key_, wakeup_at, period_)
624 end -- timer() 625 end -- timer()
625 626
626 ----- 627 -----
@@ -628,11 +629,11 @@ local configure_timers = function()
628 -- 629 --
629 -- PUBLIC LANES API 630 -- PUBLIC LANES API
630 timers = function() 631 timers = function()
631 timer_gateway:send(TGW_QUERY, "get_timers") 632 timerLinda:send(TGW_QUERY, "get_timers")
632 local _, r = timer_gateway:receive(TGW_REPLY) 633 local _, r = timerLinda:receive(TGW_REPLY)
633 return r 634 return r
634 end -- timers() 635 end -- timers()
635end 636end -- configure_timers()
636 637
637-- ################################################################################################# 638-- #################################################################################################
638-- ###################################### lanes.sleep() ############################################ 639-- ###################################### lanes.sleep() ############################################
@@ -651,8 +652,8 @@ local sleep = function(seconds_)
651 error("invalid duration " .. string_format("%q", tostring(seconds_))) 652 error("invalid duration " .. string_format("%q", tostring(seconds_)))
652 end 653 end
653 -- receive data on a channel no-one ever sends anything, thus blocking for the specified duration 654 -- receive data on a channel no-one ever sends anything, thus blocking for the specified duration
654 return timer_gateway:receive(seconds_, "ac100de1-a696-4619-b2f0-a26de9d58ab8") 655 return timerLinda:receive(seconds_, "ac100de1-a696-4619-b2f0-a26de9d58ab8")
655end -- sleep 656end -- sleep()
656 657
657-- ################################################################################################# 658-- #################################################################################################
658-- ##################################### lanes.genlock() ########################################### 659-- ##################################### lanes.genlock() ###########################################
@@ -782,7 +783,7 @@ local configure = function(settings_)
782 -- avoid pulling the whole core module as upvalue when cancel_error is enough 783 -- avoid pulling the whole core module as upvalue when cancel_error is enough
783 -- these are locals declared above, that we need to set prior to calling configure_timers() 784 -- these are locals declared above, that we need to set prior to calling configure_timers()
784 cancel_error = assert(core.cancel_error) 785 cancel_error = assert(core.cancel_error)
785 timer_gateway = assert(core.timer_gateway) 786 timerLinda = assert(core.timerLinda)
786 787
787 if settings.with_timers then 788 if settings.with_timers then
788 configure_timers(settings) 789 configure_timers(settings)