aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-12-10 17:07:09 +0100
committerBenoit Germain <benoit.germain@ubisoft.com>2024-12-10 17:07:09 +0100
commit18c708eb8fbe995efe4b06b93421db3d25e22636 (patch)
tree860a74b3a914dfacc9c959374ad4415a7f54873b /src
parent5f9ef9e1b75adc27a4ae4129cc33137aa7aaa565 (diff)
downloadlanes-18c708eb8fbe995efe4b06b93421db3d25e22636.tar.gz
lanes-18c708eb8fbe995efe4b06b93421db3d25e22636.tar.bz2
lanes-18c708eb8fbe995efe4b06b93421db3d25e22636.zip
lanes.collectgarbage() and linda:collectgarbage()
Diffstat (limited to 'src')
-rw-r--r--src/keeper.cpp55
-rw-r--r--src/keeper.hpp5
-rw-r--r--src/lanes.cpp1
-rw-r--r--src/lanes.lua1
-rw-r--r--src/linda.cpp24
5 files changed, 86 insertions, 0 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp
index e7b02e6..2d9d800 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -337,6 +337,16 @@ static void PushKeysDB(KeeperState const K_, StackIndex const idx_)
337// ################################################################################################# 337// #################################################################################################
338// ################################################################################################# 338// #################################################################################################
339 339
340// in: linda
341// out: nothing
342int keepercall_collectgarbage(lua_State* const L_)
343{
344 lua_gc(L_, LUA_GCCOLLECT, 0);
345 return 0;
346}
347
348// #################################################################################################
349
340// in: linda [, key [, ...]] 350// in: linda [, key [, ...]]
341int keepercall_count(lua_State* const L_) 351int keepercall_count(lua_State* const L_)
342{ 352{
@@ -926,6 +936,42 @@ void Keepers::DeleteKV::operator()(Keeper* const k_) const
926 936
927// ################################################################################################# 937// #################################################################################################
928 938
939void Keepers::collectGarbage()
940{
941 if (isClosing.test(std::memory_order_acquire)) {
942 assert(false); // should never close more than once in practice
943 return;
944 }
945
946 if (std::holds_alternative<std::monostate>(keeper_array)) {
947 return;
948 }
949
950 auto _gcOneKeeper = [](Keeper& keeper_) {
951 std::lock_guard<std::mutex> _guard(keeper_.mutex);
952 if (keeper_.K) {
953 lua_gc(keeper_.K, LUA_GCCOLLECT, 0);
954 }
955 };
956
957 if (std::holds_alternative<Keeper>(keeper_array)) {
958 _gcOneKeeper(std::get<Keeper>(keeper_array));
959 } else {
960 KV& _kv = std::get<KV>(keeper_array);
961
962 // NOTE: imagine some keeper state N+1 currently holds a linda that uses another keeper N, and a _gc that will make use of it
963 // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists
964 // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success
965 // which is early-outed with a keepers->nbKeepers null-check
966 for (size_t const _i : std::ranges::iota_view{ size_t{ 0 }, _kv.nbKeepers }) {
967 _gcOneKeeper(_kv.keepers[_i]);
968 }
969 }
970}
971
972// #################################################################################################
973
974
929void Keepers::close() 975void Keepers::close()
930{ 976{
931 if (isClosing.test_and_set(std::memory_order_release)) { 977 if (isClosing.test_and_set(std::memory_order_release)) {
@@ -1103,3 +1149,12 @@ void Keepers::initialize(Universe& U_, lua_State* L_, size_t const nbKeepers_, i
1103 } 1149 }
1104 } 1150 }
1105} 1151}
1152
1153// #################################################################################################
1154
1155LUAG_FUNC(collectgarbage)
1156{
1157 Universe* const _U{ Universe::Get(L_) };
1158 _U->keepers.collectGarbage();
1159 return 0;
1160}
diff --git a/src/keeper.hpp b/src/keeper.hpp
index e2ad445..c0a8dc5 100644
--- a/src/keeper.hpp
+++ b/src/keeper.hpp
@@ -73,6 +73,7 @@ struct Keepers
73 static void* operator new(size_t size_) = delete; 73 static void* operator new(size_t size_) = delete;
74 74
75 Keepers() = default; 75 Keepers() = default;
76 void collectGarbage();
76 void close(); 77 void close();
77 [[nodiscard]] 78 [[nodiscard]]
78 Keeper* getKeeper(KeeperIndex idx_); 79 Keeper* getKeeper(KeeperIndex idx_);
@@ -96,6 +97,8 @@ using keeper_api_t = lua_CFunction;
96 97
97// lua_Cfunctions to run inside a keeper state 98// lua_Cfunctions to run inside a keeper state
98[[nodiscard]] 99[[nodiscard]]
100int keepercall_collectgarbage(lua_State* L_);
101[[nodiscard]]
99int keepercall_count(lua_State* L_); 102int keepercall_count(lua_State* L_);
100[[nodiscard]] 103[[nodiscard]]
101int keepercall_destruct(lua_State* L_); 104int keepercall_destruct(lua_State* L_);
@@ -116,3 +119,5 @@ int keepercall_set(lua_State* L_);
116 119
117[[nodiscard]] 120[[nodiscard]]
118KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, StackIndex starting_index_); 121KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, StackIndex starting_index_);
122
123LUAG_FUNC(collectgarbage);
diff --git a/src/lanes.cpp b/src/lanes.cpp
index 83d01fb..f32e7af 100644
--- a/src/lanes.cpp
+++ b/src/lanes.cpp
@@ -649,6 +649,7 @@ extern LUAG_FUNC(linda);
649namespace { 649namespace {
650 namespace local { 650 namespace local {
651 static struct luaL_Reg const sLanesFunctions[] = { 651 static struct luaL_Reg const sLanesFunctions[] = {
652 { "collectgarbage", LG_collectgarbage },
652 { Universe::kFinally, Universe::InitializeFinalizer }, 653 { Universe::kFinally, Universe::InitializeFinalizer },
653 { "linda", LG_linda }, 654 { "linda", LG_linda },
654 { "nameof", LG_nameof }, 655 { "nameof", LG_nameof },
diff --git a/src/lanes.lua b/src/lanes.lua
index 8d8f25d..4df1f64 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -851,6 +851,7 @@ local configure = function(settings_)
851 851
852 -- activate full interface 852 -- activate full interface
853 lanes.cancel_error = core.cancel_error 853 lanes.cancel_error = core.cancel_error
854 lanes.collectgarbage = core.collectgarbage
854 lanes.finally = core.finally 855 lanes.finally = core.finally
855 lanes.linda = core.linda 856 lanes.linda = core.linda
856 lanes.nameof = core.nameof 857 lanes.nameof = core.nameof
diff --git a/src/linda.cpp b/src/linda.cpp
index 7af387f..4f33899 100644
--- a/src/linda.cpp
+++ b/src/linda.cpp
@@ -450,6 +450,29 @@ static LUAG_FUNC(linda_index)
450// ################################################################################################# 450// #################################################################################################
451 451
452/* 452/*
453 * (void) = linda_collectgarbage( linda_ud)
454 *
455 * Force a GC cycle in the keeper assigned to the Linda
456 */
457LUAG_FUNC(linda_collectgarbage)
458{
459 static constexpr lua_CFunction _collectgarbage{
460 +[](lua_State* const L_) {
461 Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) };
462 if (lua_gettop(L_) > 1) {
463 raise_luaL_argerror(L_, StackIndex{ 2 }, "Unexpected extra argument");
464 }
465 Keeper* const _keeper{ _linda->whichKeeper() };
466 KeeperCallResult const _pushed{ keeper_call(_keeper->K, KEEPER_API(collectgarbage), L_, _linda, StackIndex{ 0 }) };
467 return OptionalValue(_pushed, L_, "Unexpected error");
468 }
469 };
470 return Linda::ProtectedCall(L_, _collectgarbage);
471}
472
473// #################################################################################################
474
475/*
453 * [val] = linda_count( linda_ud, [slot [, ...]]) 476 * [val] = linda_count( linda_ud, [slot [, ...]])
454 * 477 *
455 * Get a count of the pending elements in the specified keys 478 * Get a count of the pending elements in the specified keys
@@ -1075,6 +1098,7 @@ namespace {
1075 { "__towatch", LG_linda_towatch }, // Decoda __towatch support 1098 { "__towatch", LG_linda_towatch }, // Decoda __towatch support
1076#endif // HAVE_DECODA_SUPPORT() 1099#endif // HAVE_DECODA_SUPPORT()
1077 { "cancel", LG_linda_cancel }, 1100 { "cancel", LG_linda_cancel },
1101 { "collectgarbage", LG_linda_collectgarbage },
1078 { "count", LG_linda_count }, 1102 { "count", LG_linda_count },
1079 { "deep", LG_linda_deep }, 1103 { "deep", LG_linda_deep },
1080 { "dump", LG_linda_dump }, 1104 { "dump", LG_linda_dump },