diff options
author | Benoit Germain <bnt.germain@gmail.com> | 2024-04-14 18:27:10 +0200 |
---|---|---|
committer | Benoit Germain <bnt.germain@gmail.com> | 2024-04-14 18:27:10 +0200 |
commit | 69d40c81d8343a1af7e0fe61fbf20a4cf5880c25 (patch) | |
tree | cbf7aa525868040820ce6743f1a30fbb59926407 /src/keeper.cpp | |
parent | 0d9c9bae120f92274e1c68f7abdebfcf2c24405d (diff) | |
parent | 00970610dc8fbd00a11d3b69e4702933a592ce9f (diff) | |
download | lanes-69d40c81d8343a1af7e0fe61fbf20a4cf5880c25.tar.gz lanes-69d40c81d8343a1af7e0fe61fbf20a4cf5880c25.tar.bz2 lanes-69d40c81d8343a1af7e0fe61fbf20a4cf5880c25.zip |
Merge branch 'master' of https://github.com/LuaLanes/lanes
Diffstat (limited to 'src/keeper.cpp')
-rw-r--r-- | src/keeper.cpp | 153 |
1 files changed, 95 insertions, 58 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp index 244cb6a..f56c50c 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -14,7 +14,7 @@ | |||
14 | --[[ | 14 | --[[ |
15 | =============================================================================== | 15 | =============================================================================== |
16 | 16 | ||
17 | Copyright (C) 2011-2023 Benoit Germain <bnt.germain@gmail.com> | 17 | Copyright (C) 2011-2024 Benoit Germain <bnt.germain@gmail.com> |
18 | 18 | ||
19 | Permission is hereby granted, free of charge, to any person obtaining a copy | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy |
20 | of this software and associated documentation files (the "Software"), to deal | 20 | of this software and associated documentation files (the "Software"), to deal |
@@ -61,12 +61,12 @@ class keeper_fifo | |||
61 | int limit{ -1 }; | 61 | int limit{ -1 }; |
62 | 62 | ||
63 | // a fifo full userdata has one uservalue, the table that holds the actual fifo contents | 63 | // a fifo full userdata has one uservalue, the table that holds the actual fifo contents |
64 | static void* operator new([[maybe_unused]] size_t size_, lua_State* L) noexcept { return lua_newuserdatauv<keeper_fifo>(L, 1); } | 64 | [[nodiscard]] static void* operator new([[maybe_unused]] size_t size_, lua_State* L) noexcept { return lua_newuserdatauv<keeper_fifo>(L, 1); } |
65 | // always embedded somewhere else or "in-place constructed" as a full userdata | 65 | // always embedded somewhere else or "in-place constructed" as a full userdata |
66 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | 66 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception |
67 | static void operator delete([[maybe_unused]] void* p_, lua_State* L) { ASSERT_L(!"should never be called") }; | 67 | static void operator delete([[maybe_unused]] void* p_, lua_State* L) { ASSERT_L(!"should never be called") }; |
68 | 68 | ||
69 | static keeper_fifo* getPtr(lua_State* L, int idx_) | 69 | [[nodiscard]] static keeper_fifo* getPtr(lua_State* L, int idx_) |
70 | { | 70 | { |
71 | return lua_tofulluserdata<keeper_fifo>(L, idx_); | 71 | return lua_tofulluserdata<keeper_fifo>(L, idx_); |
72 | } | 72 | } |
@@ -77,7 +77,7 @@ static constexpr int CONTENTS_TABLE{ 1 }; | |||
77 | // ################################################################################################## | 77 | // ################################################################################################## |
78 | 78 | ||
79 | // replaces the fifo ud by its uservalue on the stack | 79 | // replaces the fifo ud by its uservalue on the stack |
80 | static keeper_fifo* prepare_fifo_access(lua_State* L, int idx_) | 80 | [[nodiscard]] static keeper_fifo* prepare_fifo_access(lua_State* L, int idx_) |
81 | { | 81 | { |
82 | keeper_fifo* const fifo{ keeper_fifo::getPtr(L, idx_) }; | 82 | keeper_fifo* const fifo{ keeper_fifo::getPtr(L, idx_) }; |
83 | if (fifo != nullptr) | 83 | if (fifo != nullptr) |
@@ -95,7 +95,7 @@ static keeper_fifo* prepare_fifo_access(lua_State* L, int idx_) | |||
95 | 95 | ||
96 | // in: nothing | 96 | // in: nothing |
97 | // out: { first = 1, count = 0, limit = -1} | 97 | // out: { first = 1, count = 0, limit = -1} |
98 | static keeper_fifo* fifo_new(lua_State* L) | 98 | [[nodiscard]] static keeper_fifo* fifo_new(lua_State* L) |
99 | { | 99 | { |
100 | STACK_GROW(L, 2); | 100 | STACK_GROW(L, 2); |
101 | STACK_CHECK_START_REL(L, 0); | 101 | STACK_CHECK_START_REL(L, 0); |
@@ -207,52 +207,52 @@ static void push_table(lua_State* L, int idx_) | |||
207 | 207 | ||
208 | // ################################################################################################## | 208 | // ################################################################################################## |
209 | 209 | ||
210 | int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, uintptr_t magic_) | 210 | int keeper_push_linda_storage(Universe* U, Dest L, void* ptr_, uintptr_t magic_) |
211 | { | 211 | { |
212 | Keeper* const K{ which_keeper(U->keepers, magic_) }; | 212 | Keeper* const K{ which_keeper(U->keepers, magic_) }; |
213 | lua_State* const KL{ K ? K->L : nullptr }; | 213 | Source const KL{ K ? K->L : nullptr }; |
214 | if (KL == nullptr) | 214 | if (KL == nullptr) |
215 | return 0; | 215 | return 0; |
216 | STACK_GROW(KL, 4); | 216 | STACK_GROW(KL, 4); // KEEPER MAIN |
217 | STACK_CHECK_START_REL(KL, 0); | 217 | STACK_CHECK_START_REL(KL, 0); |
218 | FIFOS_KEY.pushValue(KL); // fifos | 218 | FIFOS_KEY.pushValue(KL); // fifos |
219 | lua_pushlightuserdata(KL, ptr_); // fifos ud | 219 | lua_pushlightuserdata(KL, ptr_); // fifos ud |
220 | lua_rawget(KL, -2); // fifos storage | 220 | lua_rawget(KL, -2); // fifos storage |
221 | lua_remove(KL, -2); // storage | 221 | lua_remove(KL, -2); // storage |
222 | if (!lua_istable(KL, -1)) | 222 | if (!lua_istable(KL, -1)) |
223 | { | 223 | { |
224 | lua_pop(KL, 1); // | 224 | lua_pop(KL, 1); // |
225 | STACK_CHECK(KL, 0); | 225 | STACK_CHECK(KL, 0); |
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | // move data from keeper to destination state KEEPER MAIN | 228 | // move data from keeper to destination state |
229 | lua_pushnil(KL); // storage nil | 229 | lua_pushnil(KL); // storage nil |
230 | STACK_GROW(L, 5); | 230 | STACK_GROW(L, 5); |
231 | STACK_CHECK_START_REL(L, 0); | 231 | STACK_CHECK_START_REL(L, 0); |
232 | lua_newtable(L); // out | 232 | lua_newtable(L); // out |
233 | while (lua_next(KL, -2)) // storage key fifo | 233 | while (lua_next(KL, -2)) // storage key fifo |
234 | { | 234 | { |
235 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl | 235 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl |
236 | lua_pushvalue(KL, -2); // storage key fifotbl key | 236 | lua_pushvalue(KL, -2); // storage key fifotbl key |
237 | luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key fifotbl // out key | 237 | std::ignore = luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key fifotbl // out key |
238 | STACK_CHECK(L, 2); | 238 | STACK_CHECK(L, 2); |
239 | lua_newtable(L); // out key keyout | 239 | lua_newtable(L); // out key keyout |
240 | luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key // out key keyout fifotbl | 240 | std::ignore = luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key // out key keyout fifotbl |
241 | lua_pushinteger(L, fifo->first); // out key keyout fifotbl first | 241 | lua_pushinteger(L, fifo->first); // out key keyout fifotbl first |
242 | STACK_CHECK(L, 5); | 242 | STACK_CHECK(L, 5); |
243 | lua_setfield(L, -3, "first"); // out key keyout fifotbl | 243 | lua_setfield(L, -3, "first"); // out key keyout fifotbl |
244 | lua_pushinteger(L, fifo->count); // out key keyout fifobtl count | 244 | lua_pushinteger(L, fifo->count); // out key keyout fifobtl count |
245 | STACK_CHECK(L, 5); | 245 | STACK_CHECK(L, 5); |
246 | lua_setfield(L, -3, "count"); // out key keyout fifotbl | 246 | lua_setfield(L, -3, "count"); // out key keyout fifotbl |
247 | lua_pushinteger(L, fifo->limit); // out key keyout fifotbl limit | 247 | lua_pushinteger(L, fifo->limit); // out key keyout fifotbl limit |
248 | STACK_CHECK(L, 5); | 248 | STACK_CHECK(L, 5); |
249 | lua_setfield(L, -3, "limit"); // out key keyout fifotbl | 249 | lua_setfield(L, -3, "limit"); // out key keyout fifotbl |
250 | lua_setfield(L, -2, "fifo"); // out key keyout | 250 | lua_setfield(L, -2, "fifo"); // out key keyout |
251 | lua_rawset(L, -3); // out | 251 | lua_rawset(L, -3); // out |
252 | STACK_CHECK(L, 1); | 252 | STACK_CHECK(L, 1); |
253 | } | 253 | } |
254 | STACK_CHECK(L, 1); | 254 | STACK_CHECK(L, 1); |
255 | lua_pop(KL, 1); // | 255 | lua_pop(KL, 1); // |
256 | STACK_CHECK(KL, 0); | 256 | STACK_CHECK(KL, 0); |
257 | return 1; | 257 | return 1; |
258 | } | 258 | } |
@@ -287,7 +287,7 @@ int keepercall_send(lua_State* L) | |||
287 | if( lua_isnil(L, -1)) | 287 | if( lua_isnil(L, -1)) |
288 | { | 288 | { |
289 | lua_pop(L, 1); // ud key ... fifos | 289 | lua_pop(L, 1); // ud key ... fifos |
290 | fifo_new(L); // ud key ... fifos fifo | 290 | std::ignore = fifo_new(L); // ud key ... fifos fifo |
291 | lua_pushvalue(L, 2); // ud key ... fifos fifo key | 291 | lua_pushvalue(L, 2); // ud key ... fifos fifo key |
292 | lua_pushvalue(L, -2); // ud key ... fifos fifo key fifo | 292 | lua_pushvalue(L, -2); // ud key ... fifos fifo key fifo |
293 | lua_rawset(L, -4); // ud key ... fifos fifo | 293 | lua_rawset(L, -4); // ud key ... fifos fifo |
@@ -412,7 +412,7 @@ int keepercall_limit(lua_State* L) | |||
412 | // set the new limit | 412 | // set the new limit |
413 | fifo->limit = limit; | 413 | fifo->limit = limit; |
414 | // return 0 or 1 value | 414 | // return 0 or 1 value |
415 | return lua_gettop( L); | 415 | return lua_gettop(L); |
416 | } | 416 | } |
417 | 417 | ||
418 | // ################################################################################################## | 418 | // ################################################################################################## |
@@ -465,7 +465,7 @@ int keepercall_set(lua_State* L) | |||
465 | { // fifos key [val [, ...]] nil | 465 | { // fifos key [val [, ...]] nil |
466 | // no need to wake writers in that case, because a writer can't wait on an inexistent key | 466 | // no need to wake writers in that case, because a writer can't wait on an inexistent key |
467 | lua_pop(L, 1); // fifos key [val [, ...]] | 467 | lua_pop(L, 1); // fifos key [val [, ...]] |
468 | fifo_new(L); // fifos key [val [, ...]] fifo | 468 | std::ignore = fifo_new(L); // fifos key [val [, ...]] fifo |
469 | lua_pushvalue(L, 2); // fifos key [val [, ...]] fifo key | 469 | lua_pushvalue(L, 2); // fifos key [val [, ...]] fifo key |
470 | lua_pushvalue(L, -2); // fifos key [val [, ...]] fifo key fifo | 470 | lua_pushvalue(L, -2); // fifos key [val [, ...]] fifo key fifo |
471 | lua_rawset(L, 1); // fifos key [val [, ...]] fifo | 471 | lua_rawset(L, 1); // fifos key [val [, ...]] fifo |
@@ -485,7 +485,7 @@ int keepercall_set(lua_State* L) | |||
485 | lua_insert(L, 3); // fifos key fifotbl [val [, ...]] | 485 | lua_insert(L, 3); // fifos key fifotbl [val [, ...]] |
486 | fifo_push(L, fifo, count); // fifos key fifotbl | 486 | fifo_push(L, fifo, count); // fifos key fifotbl |
487 | } | 487 | } |
488 | return should_wake_writers ? (lua_pushboolean( L, 1), 1) : 0; | 488 | return should_wake_writers ? (lua_pushboolean(L, 1), 1) : 0; |
489 | } | 489 | } |
490 | 490 | ||
491 | // ################################################################################################## | 491 | // ################################################################################################## |
@@ -627,7 +627,7 @@ void close_keepers(Universe* U) | |||
627 | } | 627 | } |
628 | for (int i = 0; i < nbKeepers; ++i) | 628 | for (int i = 0; i < nbKeepers; ++i) |
629 | { | 629 | { |
630 | MUTEX_FREE(&U->keepers->keeper_array[i].keeper_cs); | 630 | U->keepers->keeper_array[i].~Keeper(); |
631 | } | 631 | } |
632 | // free the keeper bookkeeping structure | 632 | // free the keeper bookkeeping structure |
633 | U->internal_allocator.free(U->keepers, sizeof(Keepers) + (nbKeepers - 1) * sizeof(Keeper)); | 633 | U->internal_allocator.free(U->keepers, sizeof(Keepers) + (nbKeepers - 1) * sizeof(Keeper)); |
@@ -652,12 +652,18 @@ void init_keepers(Universe* U, lua_State* L) | |||
652 | { | 652 | { |
653 | STACK_CHECK_START_REL(L, 0); // L K | 653 | STACK_CHECK_START_REL(L, 0); // L K |
654 | lua_getfield(L, 1, "nb_keepers"); // nb_keepers | 654 | lua_getfield(L, 1, "nb_keepers"); // nb_keepers |
655 | int nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; | 655 | int const nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; |
656 | lua_pop(L, 1); // | 656 | lua_pop(L, 1); // |
657 | if (nb_keepers < 1) | 657 | if (nb_keepers < 1) |
658 | { | 658 | { |
659 | std::ignore = luaL_error(L, "Bad number of keepers (%d)", nb_keepers); | 659 | luaL_error(L, "Bad number of keepers (%d)", nb_keepers); // doesn't return |
660 | } | 660 | } |
661 | STACK_CHECK(L, 0); | ||
662 | |||
663 | lua_getfield(L, 1, "keepers_gc_threshold"); // keepers_gc_threshold | ||
664 | int const keepers_gc_threshold{ static_cast<int>(lua_tointeger(L, -1)) }; | ||
665 | lua_pop(L, 1); // | ||
666 | STACK_CHECK(L, 0); | ||
661 | 667 | ||
662 | // Keepers contains an array of 1 Keeper, adjust for the actual number of keeper states | 668 | // Keepers contains an array of 1 Keeper, adjust for the actual number of keeper states |
663 | { | 669 | { |
@@ -665,10 +671,16 @@ void init_keepers(Universe* U, lua_State* L) | |||
665 | U->keepers = static_cast<Keepers*>(U->internal_allocator.alloc(bytes)); | 671 | U->keepers = static_cast<Keepers*>(U->internal_allocator.alloc(bytes)); |
666 | if (U->keepers == nullptr) | 672 | if (U->keepers == nullptr) |
667 | { | 673 | { |
668 | std::ignore = luaL_error(L, "init_keepers() failed while creating keeper array; out of memory"); | 674 | luaL_error(L, "init_keepers() failed while creating keeper array; out of memory"); // doesn't return |
669 | } | 675 | } |
670 | memset(U->keepers, 0, bytes); | 676 | U->keepers->Keepers::Keepers(); |
677 | U->keepers->gc_threshold = keepers_gc_threshold; | ||
671 | U->keepers->nb_keepers = nb_keepers; | 678 | U->keepers->nb_keepers = nb_keepers; |
679 | |||
680 | for (int i = 0; i < nb_keepers; ++i) | ||
681 | { | ||
682 | U->keepers->keeper_array[i].Keeper::Keeper(); | ||
683 | } | ||
672 | } | 684 | } |
673 | for (int i = 0; i < nb_keepers; ++i) // keepersUD | 685 | for (int i = 0; i < nb_keepers; ++i) // keepersUD |
674 | { | 686 | { |
@@ -676,14 +688,15 @@ void init_keepers(Universe* U, lua_State* L) | |||
676 | lua_State* const K{ create_state(U, L) }; | 688 | lua_State* const K{ create_state(U, L) }; |
677 | if (K == nullptr) | 689 | if (K == nullptr) |
678 | { | 690 | { |
679 | std::ignore = luaL_error(L, "init_keepers() failed while creating keeper states; out of memory"); | 691 | luaL_error(L, "init_keepers() failed while creating keeper states; out of memory"); // doesn't return |
680 | } | 692 | } |
681 | 693 | ||
682 | U->keepers->keeper_array[i].L = K; | 694 | U->keepers->keeper_array[i].L = K; |
683 | // we can trigger a GC from inside keeper_call(), where a keeper is acquired | 695 | |
684 | // from there, GC can collect a linda, which would acquire the keeper again, and deadlock the thread. | 696 | if (U->keepers->gc_threshold >= 0) |
685 | // therefore, we need a recursive mutex. | 697 | { |
686 | MUTEX_RECURSIVE_INIT(&U->keepers->keeper_array[i].keeper_cs); | 698 | lua_gc(K, LUA_GCSTOP, 0); |
699 | } | ||
687 | 700 | ||
688 | STACK_CHECK_START_ABS(K, 0); | 701 | STACK_CHECK_START_ABS(K, 0); |
689 | 702 | ||
@@ -704,7 +717,7 @@ void init_keepers(Universe* U, lua_State* L) | |||
704 | if (!lua_isnil(L, -1)) | 717 | if (!lua_isnil(L, -1)) |
705 | { | 718 | { |
706 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately | 719 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately |
707 | if (luaG_inter_copy_package(U, L, K, -1, LookupMode::ToKeeper)) | 720 | if (luaG_inter_copy_package(U, Source{ L }, Dest{ K }, -1, LookupMode::ToKeeper) != InterCopyResult::Success) |
708 | { | 721 | { |
709 | // if something went wrong, the error message is at the top of the stack | 722 | // if something went wrong, the error message is at the top of the stack |
710 | lua_remove(L, -2); // error_msg | 723 | lua_remove(L, -2); // error_msg |
@@ -735,8 +748,12 @@ void init_keepers(Universe* U, lua_State* L) | |||
735 | Keeper* which_keeper(Keepers* keepers_, uintptr_t magic_) | 748 | Keeper* which_keeper(Keepers* keepers_, uintptr_t magic_) |
736 | { | 749 | { |
737 | int const nbKeepers{ keepers_->nb_keepers }; | 750 | int const nbKeepers{ keepers_->nb_keepers }; |
738 | unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); | 751 | if (nbKeepers) |
739 | return &keepers_->keeper_array[i]; | 752 | { |
753 | unsigned int i = (unsigned int) ((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); | ||
754 | return &keepers_->keeper_array[i]; | ||
755 | } | ||
756 | return nullptr; | ||
740 | } | 757 | } |
741 | 758 | ||
742 | // ################################################################################################## | 759 | // ################################################################################################## |
@@ -745,11 +762,7 @@ Keeper* keeper_acquire(Keepers* keepers_, uintptr_t magic_) | |||
745 | { | 762 | { |
746 | int const nbKeepers{ keepers_->nb_keepers }; | 763 | int const nbKeepers{ keepers_->nb_keepers }; |
747 | // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) | 764 | // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) |
748 | if( nbKeepers == 0) | 765 | if (nbKeepers) |
749 | { | ||
750 | return nullptr; | ||
751 | } | ||
752 | else | ||
753 | { | 766 | { |
754 | /* | 767 | /* |
755 | * Any hashing will do that maps pointers to 0..GNbKeepers-1 | 768 | * Any hashing will do that maps pointers to 0..GNbKeepers-1 |
@@ -760,11 +773,11 @@ Keeper* keeper_acquire(Keepers* keepers_, uintptr_t magic_) | |||
760 | */ | 773 | */ |
761 | unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); | 774 | unsigned int i = (unsigned int)((magic_ >> KEEPER_MAGIC_SHIFT) % nbKeepers); |
762 | Keeper* K = &keepers_->keeper_array[i]; | 775 | Keeper* K = &keepers_->keeper_array[i]; |
763 | 776 | K->m_mutex.lock(); | |
764 | MUTEX_LOCK( &K->keeper_cs); | ||
765 | //++ K->count; | 777 | //++ K->count; |
766 | return K; | 778 | return K; |
767 | } | 779 | } |
780 | return nullptr; | ||
768 | } | 781 | } |
769 | 782 | ||
770 | // ################################################################################################## | 783 | // ################################################################################################## |
@@ -774,7 +787,7 @@ void keeper_release(Keeper* K) | |||
774 | //-- K->count; | 787 | //-- K->count; |
775 | if (K) | 788 | if (K) |
776 | { | 789 | { |
777 | MUTEX_UNLOCK(&K->keeper_cs); | 790 | K->m_mutex.unlock(); |
778 | } | 791 | } |
779 | } | 792 | } |
780 | 793 | ||
@@ -827,21 +840,45 @@ int keeper_call(Universe* U, lua_State* K, keeper_api_t func_, lua_State* L, voi | |||
827 | 840 | ||
828 | lua_pushlightuserdata(K, linda); | 841 | lua_pushlightuserdata(K, linda); |
829 | 842 | ||
830 | if ((args == 0) || luaG_inter_copy(U, L, K, args, LookupMode::ToKeeper) == 0) // L->K | 843 | if ((args == 0) || luaG_inter_copy(U, Source{ L }, Dest{ K }, args, LookupMode::ToKeeper) == InterCopyResult::Success) // L->K |
831 | { | 844 | { |
832 | lua_call(K, 1 + args, LUA_MULTRET); | 845 | lua_call(K, 1 + args, LUA_MULTRET); |
833 | |||
834 | retvals = lua_gettop(K) - Ktos; | 846 | retvals = lua_gettop(K) - Ktos; |
835 | // note that this can raise a luaL_error while the keeper state (and its mutex) is acquired | 847 | // note that this can raise a luaL_error while the keeper state (and its mutex) is acquired |
836 | // this may interrupt a lane, causing the destruction of the underlying OS thread | 848 | // this may interrupt a lane, causing the destruction of the underlying OS thread |
837 | // after this, another lane making use of this keeper can get an error code from the mutex-locking function | 849 | // after this, another lane making use of this keeper can get an error code from the mutex-locking function |
838 | // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) | 850 | // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) |
839 | if ((retvals > 0) && luaG_inter_move(U, K, L, retvals, LookupMode::FromKeeper) != 0) // K->L | 851 | if ((retvals > 0) && luaG_inter_move(U, Source{ K }, Dest{ L }, retvals, LookupMode::FromKeeper) != InterCopyResult::Success) // K->L |
840 | { | 852 | { |
841 | retvals = -1; | 853 | retvals = -1; |
842 | } | 854 | } |
843 | } | 855 | } |
844 | // whatever happens, restore the stack to where it was at the origin | 856 | // whatever happens, restore the stack to where it was at the origin |
845 | lua_settop(K, Ktos); | 857 | lua_settop(K, Ktos); |
858 | |||
859 | // don't do this for this particular function, as it is only called during Linda destruction, and we don't want to raise an error, ever | ||
860 | if (func_ != KEEPER_API(clear)) [[unlikely]] | ||
861 | { | ||
862 | // since keeper state GC is stopped, let's run a step once in a while if required | ||
863 | int const gc_threshold{ U->keepers->gc_threshold }; | ||
864 | if (gc_threshold == 0) [[unlikely]] | ||
865 | { | ||
866 | lua_gc(K, LUA_GCSTEP, 0); | ||
867 | } | ||
868 | else if (gc_threshold > 0) [[likely]] | ||
869 | { | ||
870 | int const gc_usage{ lua_gc(K, LUA_GCCOUNT, 0) }; | ||
871 | if (gc_usage >= gc_threshold) | ||
872 | { | ||
873 | lua_gc(K, LUA_GCCOLLECT, 0); | ||
874 | int const gc_usage_after{ lua_gc(K, LUA_GCCOUNT, 0) }; | ||
875 | if (gc_usage_after > gc_threshold) [[unlikely]] | ||
876 | { | ||
877 | luaL_error(L, "Keeper GC threshold is too low, need at least %d", gc_usage_after); | ||
878 | } | ||
879 | } | ||
880 | } | ||
881 | } | ||
882 | |||
846 | return retvals; | 883 | return retvals; |
847 | } | 884 | } |