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/universe.cpp | |
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/universe.cpp')
-rw-r--r-- | src/universe.cpp | 40 |
1 files changed, 39 insertions, 1 deletions
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; |