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 | }; |
