aboutsummaryrefslogtreecommitdiff
path: root/src/keeper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/keeper.cpp')
-rw-r--r--src/keeper.cpp55
1 files changed, 55 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}