diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-12-10 17:07:09 +0100 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-12-10 17:07:09 +0100 |
| commit | 18c708eb8fbe995efe4b06b93421db3d25e22636 (patch) | |
| tree | 860a74b3a914dfacc9c959374ad4415a7f54873b /src | |
| parent | 5f9ef9e1b75adc27a4ae4129cc33137aa7aaa565 (diff) | |
| download | lanes-18c708eb8fbe995efe4b06b93421db3d25e22636.tar.gz lanes-18c708eb8fbe995efe4b06b93421db3d25e22636.tar.bz2 lanes-18c708eb8fbe995efe4b06b93421db3d25e22636.zip | |
lanes.collectgarbage() and linda:collectgarbage()
Diffstat (limited to 'src')
| -rw-r--r-- | src/keeper.cpp | 55 | ||||
| -rw-r--r-- | src/keeper.hpp | 5 | ||||
| -rw-r--r-- | src/lanes.cpp | 1 | ||||
| -rw-r--r-- | src/lanes.lua | 1 | ||||
| -rw-r--r-- | src/linda.cpp | 24 |
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 | ||
| 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 | } | ||
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]] |
| 100 | int keepercall_collectgarbage(lua_State* L_); | ||
| 101 | [[nodiscard]] | ||
| 99 | int keepercall_count(lua_State* L_); | 102 | int keepercall_count(lua_State* L_); |
| 100 | [[nodiscard]] | 103 | [[nodiscard]] |
| 101 | int keepercall_destruct(lua_State* L_); | 104 | int keepercall_destruct(lua_State* L_); |
| @@ -116,3 +119,5 @@ int keepercall_set(lua_State* L_); | |||
| 116 | 119 | ||
| 117 | [[nodiscard]] | 120 | [[nodiscard]] |
| 118 | KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, StackIndex starting_index_); | 121 | KeeperCallResult keeper_call(KeeperState K_, keeper_api_t func_, lua_State* L_, Linda* linda_, StackIndex starting_index_); |
| 122 | |||
| 123 | LUAG_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); | |||
| 649 | namespace { | 649 | namespace { |
| 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 | */ | ||
| 457 | LUAG_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 }, |
