diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-28 18:01:55 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-28 18:01:55 +0200 |
commit | 92944be3c3718095efa38e2a8db94844b1c7f739 (patch) | |
tree | e050cc4e493f6bc69be6b00b9b0562295ba5b123 /src | |
parent | 8d7791f3eb1c5fc449490845254b59fdde30e9e0 (diff) | |
download | lanes-92944be3c3718095efa38e2a8db94844b1c7f739.tar.gz lanes-92944be3c3718095efa38e2a8db94844b1c7f739.tar.bz2 lanes-92944be3c3718095efa38e2a8db94844b1c7f739.zip |
New Lanes finalizer API lanes.finally()
Diffstat (limited to 'src')
-rw-r--r-- | src/lanes.cpp | 1 | ||||
-rw-r--r-- | src/lanes.lua | 1 | ||||
-rw-r--r-- | src/state.cpp | 2 | ||||
-rw-r--r-- | src/universe.cpp | 40 | ||||
-rw-r--r-- | src/universe.h | 3 |
5 files changed, 45 insertions, 2 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index 0ea0900..109fba4 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -598,6 +598,7 @@ namespace { | |||
598 | { "set_thread_affinity", LG_set_thread_affinity }, | 598 | { "set_thread_affinity", LG_set_thread_affinity }, |
599 | { "nameof", luaG_nameof }, | 599 | { "nameof", luaG_nameof }, |
600 | { "register", LG_register }, | 600 | { "register", LG_register }, |
601 | { Universe::kFinally, Universe::InitializeFinalizer }, | ||
601 | { "set_singlethreaded", LG_set_singlethreaded }, | 602 | { "set_singlethreaded", LG_set_singlethreaded }, |
602 | { nullptr, nullptr } | 603 | { nullptr, nullptr } |
603 | }; | 604 | }; |
diff --git a/src/lanes.lua b/src/lanes.lua index e75e840..6616667 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -799,6 +799,7 @@ local configure = function(settings_) | |||
799 | lanes.null = core.null | 799 | lanes.null = core.null |
800 | lanes.require = core.require | 800 | lanes.require = core.require |
801 | lanes.register = core.register | 801 | lanes.register = core.register |
802 | lanes.finally = core.finally | ||
802 | lanes.set_singlethreaded = core.set_singlethreaded | 803 | lanes.set_singlethreaded = core.set_singlethreaded |
803 | lanes.set_thread_affinity = core.set_thread_affinity | 804 | lanes.set_thread_affinity = core.set_thread_affinity |
804 | lanes.set_thread_priority = core.set_thread_priority | 805 | lanes.set_thread_priority = core.set_thread_priority |
diff --git a/src/state.cpp b/src/state.cpp index 5a1d2fb..d9f5499 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
@@ -209,7 +209,7 @@ static void copy_one_time_settings(Universe* U_, SourceState L1_, DestState L2_) | |||
209 | 209 | ||
210 | // ################################################################################################# | 210 | // ################################################################################################# |
211 | 211 | ||
212 | static constexpr char const* kOnStateCreate{ "on_state_create" }; | 212 | static constexpr char const* kOnStateCreate{ "on_state_create" }; // update lanes.lua if the name changes! |
213 | 213 | ||
214 | void InitializeOnStateCreate(Universe* U_, lua_State* L_) | 214 | void InitializeOnStateCreate(Universe* U_, lua_State* L_) |
215 | { | 215 | { |
diff --git a/src/universe.cpp b/src/universe.cpp index 5794048..3271e70 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -197,6 +197,28 @@ void Universe::initializeAllocatorFunction(lua_State* L_) | |||
197 | 197 | ||
198 | // ################################################################################################# | 198 | // ################################################################################################# |
199 | 199 | ||
200 | // should be called ONLY from the state that created the universe | ||
201 | int Universe::InitializeFinalizer(lua_State* L_) | ||
202 | { | ||
203 | luaL_argcheck(L_, lua_gettop(L_) <= 1, 1, "too many arguments"); // L_: f? | ||
204 | lua_settop(L_, 1); // L_: f|nil | ||
205 | luaL_argcheck(L_, lua_isnoneornil(L_, 1) || lua_isfunction(L_, 1), 1, "finalizer should be a function"); | ||
206 | |||
207 | // make sure we are only called from the Master Lua State! | ||
208 | kUniverseFullRegKey.pushValue(L_); // L_: f U | ||
209 | if (lua_type_as_enum(L_, -1) != LuaType::USERDATA) { | ||
210 | raise_luaL_error(L_, "lanes.%s called from inside a lane", kFinally); | ||
211 | } | ||
212 | lua_pop(L_, 1); // L_: f | ||
213 | STACK_GROW(L_, 3); | ||
214 | // _R[kFinalizerRegKey] = f | ||
215 | kFinalizerRegKey.setValue(L_, [](lua_State* L_) { lua_insert(L_, -2); }); // L_: | ||
216 | // no need to adjust the stack, Lua does this for us | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | // ################################################################################################# | ||
221 | |||
200 | /* | 222 | /* |
201 | * Initialize keeper states | 223 | * Initialize keeper states |
202 | * | 224 | * |
@@ -373,9 +395,22 @@ int universe_gc(lua_State* L_) | |||
373 | { | 395 | { |
374 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; | 396 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; |
375 | std::string_view const _op_string{ lua_tostringview(L_, lua_upvalueindex(2)) }; | 397 | std::string_view const _op_string{ lua_tostringview(L_, lua_upvalueindex(2)) }; |
376 | Universe* const _U{ lua_tofulluserdata<Universe>(L_, 1) }; | 398 | STACK_CHECK_START_ABS(L_, 1); |
399 | Universe* const _U{ lua_tofulluserdata<Universe>(L_, 1) }; // L_: U | ||
377 | _U->terminateFreeRunningLanes(L_, _shutdown_timeout, which_cancel_op(_op_string)); | 400 | _U->terminateFreeRunningLanes(L_, _shutdown_timeout, which_cancel_op(_op_string)); |
378 | 401 | ||
402 | // invoke the function installed by lanes.finally() | ||
403 | kFinalizerRegKey.pushValue(L_); // L_: U finalizer|nil | ||
404 | if (!lua_isnil(L_, -1)) { | ||
405 | lua_pcall(L_, 0, 0, 0); // L_: U | ||
406 | // discard any error that might have occured | ||
407 | lua_settop(L_, 1); | ||
408 | } else { | ||
409 | lua_pop(L_, 1); // L_: U | ||
410 | } | ||
411 | // in case of error, the message is pushed on the stack | ||
412 | STACK_CHECK(L_, 1); | ||
413 | |||
379 | // no need to mutex-protect this as all threads in the universe are gone at that point | 414 | // no need to mutex-protect this as all threads in the universe are gone at that point |
380 | if (_U->timerLinda != nullptr) { // test in case some early internal error prevented Lanes from creating the deep timer | 415 | if (_U->timerLinda != nullptr) { // test in case some early internal error prevented Lanes from creating the deep timer |
381 | [[maybe_unused]] int const _prev_ref_count{ _U->timerLinda->refcount.fetch_sub(1, std::memory_order_relaxed) }; | 416 | [[maybe_unused]] int const _prev_ref_count{ _U->timerLinda->refcount.fetch_sub(1, std::memory_order_relaxed) }; |
@@ -389,6 +424,9 @@ int universe_gc(lua_State* L_) | |||
389 | // remove the protected allocator, if any | 424 | // remove the protected allocator, if any |
390 | _U->protectedAllocator.removeFrom(L_); | 425 | _U->protectedAllocator.removeFrom(L_); |
391 | 426 | ||
427 | // no longer found in the registry | ||
428 | kUniverseFullRegKey.setValue(L_, [](lua_State* L_) { lua_pushnil(L_); }); | ||
429 | kUniverseLightRegKey.setValue(L_, [](lua_State* L_) { lua_pushnil(L_); }); | ||
392 | _U->Universe::~Universe(); | 430 | _U->Universe::~Universe(); |
393 | 431 | ||
394 | return 0; | 432 | return 0; |
diff --git a/src/universe.h b/src/universe.h index f5b31a3..4be6a9a 100644 --- a/src/universe.h +++ b/src/universe.h | |||
@@ -120,6 +120,8 @@ static constexpr RegistryUniqueKey kUniverseLightRegKey{ 0x48BBE9CEAB0BA04Full } | |||
120 | class Universe | 120 | class Universe |
121 | { | 121 | { |
122 | public: | 122 | public: |
123 | static constexpr char const* kFinally{ "finally" }; // update lanes.lua if the name changes! | ||
124 | |||
123 | #ifdef PLATFORM_LINUX | 125 | #ifdef PLATFORM_LINUX |
124 | // Linux needs to check, whether it's been run as root | 126 | // Linux needs to check, whether it's been run as root |
125 | bool const sudo{ geteuid() == 0 }; | 127 | bool const sudo{ geteuid() == 0 }; |
@@ -180,6 +182,7 @@ class Universe | |||
180 | 182 | ||
181 | void closeKeepers(); | 183 | void closeKeepers(); |
182 | void initializeAllocatorFunction(lua_State* L_); | 184 | void initializeAllocatorFunction(lua_State* L_); |
185 | static int InitializeFinalizer(lua_State* L_); | ||
183 | void initializeKeepers(lua_State* L_); | 186 | void initializeKeepers(lua_State* L_); |
184 | void terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTimeout_, CancelOp op_); | 187 | void terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTimeout_, CancelOp op_); |
185 | }; | 188 | }; |