diff options
Diffstat (limited to 'src/keeper.cpp')
-rw-r--r-- | src/keeper.cpp | 55 |
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 | ||
342 | int 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 [, ...]] |
341 | int keepercall_count(lua_State* const L_) | 351 | int 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 | ||
939 | void 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 | |||
929 | void Keepers::close() | 975 | void 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 | |||
1155 | LUAG_FUNC(collectgarbage) | ||
1156 | { | ||
1157 | Universe* const _U{ Universe::Get(L_) }; | ||
1158 | _U->keepers.collectGarbage(); | ||
1159 | return 0; | ||
1160 | } | ||