aboutsummaryrefslogtreecommitdiff
path: root/src/universe.cpp
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-05-28 18:01:55 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-05-28 18:01:55 +0200
commit92944be3c3718095efa38e2a8db94844b1c7f739 (patch)
treee050cc4e493f6bc69be6b00b9b0562295ba5b123 /src/universe.cpp
parent8d7791f3eb1c5fc449490845254b59fdde30e9e0 (diff)
downloadlanes-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.cpp40
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
201int 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;