aboutsummaryrefslogtreecommitdiff
path: root/src
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
parent8d7791f3eb1c5fc449490845254b59fdde30e9e0 (diff)
downloadlanes-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.cpp1
-rw-r--r--src/lanes.lua1
-rw-r--r--src/state.cpp2
-rw-r--r--src/universe.cpp40
-rw-r--r--src/universe.h3
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
212static constexpr char const* kOnStateCreate{ "on_state_create" }; 212static constexpr char const* kOnStateCreate{ "on_state_create" }; // update lanes.lua if the name changes!
213 213
214void InitializeOnStateCreate(Universe* U_, lua_State* L_) 214void 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
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;
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 }
120class Universe 120class 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};