diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-31 11:40:28 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-31 11:40:28 +0200 |
commit | a65a84cfad4eae38e5e84b1ab11f60a62833f287 (patch) | |
tree | 3d3b6cc88c188f2c34d3283e081316d6cc05ae83 /src | |
parent | 731556711e453a501f1d1d06a6013b8fbd53414e (diff) | |
download | lanes-a65a84cfad4eae38e5e84b1ab11f60a62833f287.tar.gz lanes-a65a84cfad4eae38e5e84b1ab11f60a62833f287.tar.bz2 lanes-a65a84cfad4eae38e5e84b1ab11f60a62833f287.zip |
Improved multi-keeper tests
Diffstat (limited to 'src')
-rw-r--r-- | src/deep.cpp | 9 | ||||
-rw-r--r-- | src/lanes.cpp | 2 | ||||
-rw-r--r-- | src/lanes.lua | 37 |
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() | ||
126 | void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_) | 127 | void 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 | |||
376 | local timers = timer | 376 | local timers = timer |
377 | local timer_lane = nil | 377 | local 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 |
380 | local timer_gateway | 380 | -- is upvalue of timer stuff and lanes.sleep() |
381 | local timerLinda | ||
381 | 382 | ||
382 | local TGW_KEY = "(timer control)" -- the key does not matter, a 'weird' key may help debugging | 383 | local TGW_KEY = "(timer control)" -- the key does not matter, a 'weird' key may help debugging |
383 | local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)" | 384 | local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)" |
@@ -387,7 +388,7 @@ local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)" | |||
387 | local configure_timers = function() | 388 | local 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() |
635 | end | 636 | end -- 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") |
655 | end -- sleep | 656 | end -- 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) |