diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-03 15:53:34 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-03 15:53:34 +0200 |
| commit | 44c617f7b756052c7cd059c96f89b85f0f5ec96c (patch) | |
| tree | a9ac504d7ffa09500c9ea17bab963f1016f6fe79 /src | |
| parent | 420e50697cd036a0d8ea1601961bd6974703ade1 (diff) | |
| download | lanes-44c617f7b756052c7cd059c96f89b85f0f5ec96c.tar.gz lanes-44c617f7b756052c7cd059c96f89b85f0f5ec96c.tar.bz2 lanes-44c617f7b756052c7cd059c96f89b85f0f5ec96c.zip | |
Moved lanes.sleep implementation to the C-side
Diffstat (limited to 'src')
| -rw-r--r-- | src/cancel.h | 1 | ||||
| -rw-r--r-- | src/deep.cpp | 18 | ||||
| -rw-r--r-- | src/deep.h | 2 | ||||
| -rw-r--r-- | src/lanes.cpp | 38 | ||||
| -rw-r--r-- | src/lanes.lua | 26 | ||||
| -rw-r--r-- | src/uniquekey.h | 6 |
6 files changed, 57 insertions, 34 deletions
diff --git a/src/cancel.h b/src/cancel.h index bac8b05..d60903c 100644 --- a/src/cancel.h +++ b/src/cancel.h | |||
| @@ -26,6 +26,7 @@ class Lane; // forward | |||
| 26 | enum class CancelRequest | 26 | enum class CancelRequest |
| 27 | { | 27 | { |
| 28 | None, // no pending cancel request | 28 | None, // no pending cancel request |
| 29 | // TODO: add a Wake mode: user wants to wake the waiting lindas (in effect resulting in a timeout before the initial operation duration) | ||
| 29 | Soft, // user wants the lane to cancel itself manually on cancel_test() | 30 | Soft, // user wants the lane to cancel itself manually on cancel_test() |
| 30 | Hard // user wants the lane to be interrupted (meaning code won't return from those functions) from inside linda:send/receive calls | 31 | Hard // user wants the lane to be interrupted (meaning code won't return from those functions) from inside linda:send/receive calls |
| 31 | }; | 32 | }; |
diff --git a/src/deep.cpp b/src/deep.cpp index 34cc4b4..76397ae 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
| @@ -191,7 +191,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
| 191 | STACK_GROW(L_, 7); | 191 | STACK_GROW(L_, 7); |
| 192 | 192 | ||
| 193 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) | 193 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
| 194 | DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy | 194 | DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy |
| 195 | LUA_ASSERT(L_, _proxy); | 195 | LUA_ASSERT(L_, _proxy); |
| 196 | *_proxy = prelude_; | 196 | *_proxy = prelude_; |
| 197 | prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data | 197 | prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data |
| @@ -268,10 +268,10 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_, | |||
| 268 | } | 268 | } |
| 269 | } | 269 | } |
| 270 | } | 270 | } |
| 271 | STACK_CHECK(L_, 3); // DPC proxy metatable | 271 | STACK_CHECK(L_, 3); // L_: DPC proxy metatable |
| 272 | LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA); | 272 | LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA); |
| 273 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 273 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
| 274 | lua_setmetatable(L_, -2); // DPC proxy | 274 | lua_setmetatable(L_, -2); // L_: DPC proxy |
| 275 | 275 | ||
| 276 | // If we're here, we obviously had to create a new proxy, so cache it. | 276 | // If we're here, we obviously had to create a new proxy, so cache it. |
| 277 | lua_pushlightuserdata(L_, prelude_); // L_: DPC proxy deep | 277 | lua_pushlightuserdata(L_, prelude_); // L_: DPC proxy deep |
| @@ -375,3 +375,15 @@ DeepPrelude* DeepFactory::toDeep(lua_State* const L_, int const index_) const | |||
| 375 | DeepPrelude** const _proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index_) }; | 375 | DeepPrelude** const _proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index_) }; |
| 376 | return *_proxy; | 376 | return *_proxy; |
| 377 | } | 377 | } |
| 378 | |||
| 379 | // ################################################################################################# | ||
| 380 | |||
| 381 | void DeepPrelude::push(lua_State* L_) const | ||
| 382 | { | ||
| 383 | STACK_CHECK_START_REL(L_, 0); | ||
| 384 | kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC | ||
| 385 | lua_pushlightuserdata(L_, const_cast<DeepPrelude*>(this)); // L_: DPC this | ||
| 386 | lua_rawget(L_, -2); // L_: DPC deep | ||
| 387 | lua_remove(L_, -2); // L_: deep | ||
| 388 | STACK_CHECK(L_, 1); | ||
| 389 | } | ||
| @@ -43,6 +43,8 @@ struct DeepPrelude | |||
| 43 | : factory{ factory_ } | 43 | : factory{ factory_ } |
| 44 | { | 44 | { |
| 45 | } | 45 | } |
| 46 | |||
| 47 | void push(lua_State* L_) const; | ||
| 46 | }; | 48 | }; |
| 47 | 49 | ||
| 48 | // ################################################################################################# | 50 | // ################################################################################################# |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 41450f3..25f44d9 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -161,6 +161,33 @@ LUAG_FUNC(set_thread_affinity) | |||
| 161 | 161 | ||
| 162 | // ################################################################################################# | 162 | // ################################################################################################# |
| 163 | 163 | ||
| 164 | LUAG_FUNC(sleep) | ||
| 165 | { | ||
| 166 | extern LUAG_FUNC(linda_receive); | ||
| 167 | |||
| 168 | Universe* const _U{ Universe::Get(L_) }; | ||
| 169 | lua_settop(L_, 1); | ||
| 170 | lua_pushcfunction(L_, LG_linda_receive); // L_: duration|nil receive() | ||
| 171 | STACK_CHECK_START_REL(L_, 0); // we pushed the function we intend to call, now prepare the arguments | ||
| 172 | _U->timerLinda->push(L_); // L_: duration|nil receive() timerLinda | ||
| 173 | if (lua_tostringview(L_, 1) == "indefinitely") { | ||
| 174 | lua_pushnil(L_); // L_: duration? receive() timerLinda nil | ||
| 175 | } else if (lua_isnoneornil(L_, 1)) { | ||
| 176 | lua_pushnumber(L_, 0); // L_: duration? receive() timerLinda 0 | ||
| 177 | } else if (!lua_isnumber(L_, 1)) { | ||
| 178 | raise_luaL_argerror(L_, 1, "invalid duration"); | ||
| 179 | } | ||
| 180 | else { | ||
| 181 | lua_pushnumber(L_, lua_tonumber(L_, 1)); // L_: duration? receive() timerLinda duration | ||
| 182 | } | ||
| 183 | std::ignore = lua_pushstringview(L_, "ac100de1-a696-4619-b2f0-a26de9d58ab8"); // L_: duration? receive() timerLinda duration key | ||
| 184 | STACK_CHECK(L_, 3); // 3 arguments ready | ||
| 185 | lua_call(L_, 3, LUA_MULTRET); // timerLinda:receive(duration,key) // L_: duration? result... | ||
| 186 | return lua_gettop(L_) - 1; | ||
| 187 | } | ||
| 188 | |||
| 189 | // ################################################################################################# | ||
| 190 | |||
| 164 | // --- If a client wants to transfer stuff of a given module from the current state to another Lane, the module must be required | 191 | // --- If a client wants to transfer stuff of a given module from the current state to another Lane, the module must be required |
| 165 | // with lanes.require, that will call the regular 'require', then populate the lookup database in the source lane | 192 | // with lanes.require, that will call the regular 'require', then populate the lookup database in the source lane |
| 166 | // module = lanes.require( "modname") | 193 | // module = lanes.require( "modname") |
| @@ -592,15 +619,16 @@ extern LUAG_FUNC(linda); | |||
| 592 | namespace { | 619 | namespace { |
| 593 | namespace local { | 620 | namespace local { |
| 594 | static struct luaL_Reg const sLanesFunctions[] = { | 621 | static struct luaL_Reg const sLanesFunctions[] = { |
| 622 | { Universe::kFinally, Universe::InitializeFinalizer }, | ||
| 595 | { "linda", LG_linda }, | 623 | { "linda", LG_linda }, |
| 596 | { "now_secs", LG_now_secs }, | ||
| 597 | { "wakeup_conv", LG_wakeup_conv }, | ||
| 598 | { "set_thread_priority", LG_set_thread_priority }, | ||
| 599 | { "set_thread_affinity", LG_set_thread_affinity }, | ||
| 600 | { "nameof", LG_nameof }, | 624 | { "nameof", LG_nameof }, |
| 625 | { "now_secs", LG_now_secs }, | ||
| 601 | { "register", LG_register }, | 626 | { "register", LG_register }, |
| 602 | { Universe::kFinally, Universe::InitializeFinalizer }, | ||
| 603 | { "set_singlethreaded", LG_set_singlethreaded }, | 627 | { "set_singlethreaded", LG_set_singlethreaded }, |
| 628 | { "set_thread_priority", LG_set_thread_priority }, | ||
| 629 | { "set_thread_affinity", LG_set_thread_affinity }, | ||
| 630 | { "sleep", LG_sleep }, | ||
| 631 | { "wakeup_conv", LG_wakeup_conv }, | ||
| 604 | { nullptr, nullptr } | 632 | { nullptr, nullptr } |
| 605 | }; | 633 | }; |
| 606 | } // namespace local | 634 | } // namespace local |
diff --git a/src/lanes.lua b/src/lanes.lua index f5e81d4..4f11033 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
| @@ -644,26 +644,6 @@ local configure_timers = function() | |||
| 644 | end -- configure_timers() | 644 | end -- configure_timers() |
| 645 | 645 | ||
| 646 | -- ################################################################################################# | 646 | -- ################################################################################################# |
| 647 | -- ###################################### lanes.sleep() ############################################ | ||
| 648 | -- ################################################################################################# | ||
| 649 | |||
| 650 | -- nil, "timeout" = sleep([seconds_]) | ||
| 651 | -- | ||
| 652 | -- PUBLIC LANES API | ||
| 653 | local sleep = function(seconds_) | ||
| 654 | local type = type(seconds_) | ||
| 655 | if type == "string" then | ||
| 656 | seconds_ = (seconds_ ~= 'indefinitely') and tonumber(seconds_) or nil | ||
| 657 | elseif type == "nil" then | ||
| 658 | seconds_ = 0 | ||
| 659 | elseif type ~= "number" then | ||
| 660 | error("invalid duration " .. string_format("%q", tostring(seconds_))) | ||
| 661 | end | ||
| 662 | -- receive data on a channel no-one ever sends anything, thus blocking for the specified duration | ||
| 663 | return timerLinda:receive(seconds_, "ac100de1-a696-4619-b2f0-a26de9d58ab8") | ||
| 664 | end -- sleep() | ||
| 665 | |||
| 666 | -- ################################################################################################# | ||
| 667 | -- ##################################### lanes.genlock() ########################################### | 647 | -- ##################################### lanes.genlock() ########################################### |
| 668 | -- ################################################################################################# | 648 | -- ################################################################################################# |
| 669 | -- These functions are just surface sugar, but make solutions easier to read. | 649 | -- These functions are just surface sugar, but make solutions easier to read. |
| @@ -799,22 +779,22 @@ local configure = function(settings_) | |||
| 799 | 779 | ||
| 800 | -- activate full interface | 780 | -- activate full interface |
| 801 | lanes.cancel_error = core.cancel_error | 781 | lanes.cancel_error = core.cancel_error |
| 782 | lanes.finally = core.finally | ||
| 802 | lanes.linda = core.linda | 783 | lanes.linda = core.linda |
| 803 | lanes.nameof = core.nameof | 784 | lanes.nameof = core.nameof |
| 804 | lanes.now_secs = core.now_secs | 785 | lanes.now_secs = core.now_secs |
| 805 | lanes.null = core.null | 786 | lanes.null = core.null |
| 806 | lanes.require = core.require | ||
| 807 | lanes.register = core.register | 787 | lanes.register = core.register |
| 808 | lanes.finally = core.finally | 788 | lanes.require = core.require |
| 809 | lanes.set_singlethreaded = core.set_singlethreaded | 789 | lanes.set_singlethreaded = core.set_singlethreaded |
| 810 | lanes.set_thread_affinity = core.set_thread_affinity | 790 | lanes.set_thread_affinity = core.set_thread_affinity |
| 811 | lanes.set_thread_priority = core.set_thread_priority | 791 | lanes.set_thread_priority = core.set_thread_priority |
| 792 | lanes.sleep = core.sleep | ||
| 812 | lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false | 793 | lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false |
| 813 | 794 | ||
| 814 | lanes.gen = gen | 795 | lanes.gen = gen |
| 815 | lanes.genatomic = genatomic | 796 | lanes.genatomic = genatomic |
| 816 | lanes.genlock = genlock | 797 | lanes.genlock = genlock |
| 817 | lanes.sleep = sleep | ||
| 818 | lanes.timer = timer | 798 | lanes.timer = timer |
| 819 | lanes.timer_lane = timer_lane | 799 | lanes.timer_lane = timer_lane |
| 820 | lanes.timers = timers | 800 | lanes.timers = timers |
diff --git a/src/uniquekey.h b/src/uniquekey.h index cfc8ab0..7e86cbe 100644 --- a/src/uniquekey.h +++ b/src/uniquekey.h | |||
| @@ -59,7 +59,7 @@ class RegistryUniqueKey | |||
| 59 | } | 59 | } |
| 60 | // --------------------------------------------------------------------------------------------- | 60 | // --------------------------------------------------------------------------------------------- |
| 61 | template <typename OP> | 61 | template <typename OP> |
| 62 | void setValue(lua_State* L_, OP operation_) const | 62 | void setValue(lua_State* const L_, OP operation_) const |
| 63 | { | 63 | { |
| 64 | // Note we can't check stack consistency because operation is not always a push (could be insert, replace, whatever) | 64 | // Note we can't check stack consistency because operation is not always a push (could be insert, replace, whatever) |
| 65 | pushKey(L_); // ... key | 65 | pushKey(L_); // ... key |
| @@ -91,7 +91,7 @@ class RegistryUniqueKey | |||
| 91 | } | 91 | } |
| 92 | // --------------------------------------------------------------------------------------------- | 92 | // --------------------------------------------------------------------------------------------- |
| 93 | // equivalent to luaL_getsubtable | 93 | // equivalent to luaL_getsubtable |
| 94 | [[nodiscard]] bool getSubTable(lua_State* const L_, int narr_, int nrec_) const | 94 | [[nodiscard]] bool getSubTable(lua_State* const L_, int const narr_, int const nrec_) const |
| 95 | { | 95 | { |
| 96 | STACK_CHECK_START_REL(L_, 0); | 96 | STACK_CHECK_START_REL(L_, 0); |
| 97 | pushValue(L_); // L_: {}|nil | 97 | pushValue(L_); // L_: {}|nil |
| @@ -108,7 +108,7 @@ class RegistryUniqueKey | |||
| 108 | return false; | 108 | return false; |
| 109 | } | 109 | } |
| 110 | // --------------------------------------------------------------------------------------------- | 110 | // --------------------------------------------------------------------------------------------- |
| 111 | void getSubTableMode(lua_State* L_, const char* mode_) const | 111 | void getSubTableMode(lua_State* const L_, char const* const mode_) const |
| 112 | { | 112 | { |
| 113 | STACK_CHECK_START_REL(L_, 0); | 113 | STACK_CHECK_START_REL(L_, 0); |
| 114 | if (!getSubTable(L_, 0, 0)) { // L_: {} | 114 | if (!getSubTable(L_, 0, 0)) { // L_: {} |
