diff options
Diffstat (limited to 'src/keeper.cpp')
-rw-r--r-- | src/keeper.cpp | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/src/keeper.cpp b/src/keeper.cpp index 650789b..3e26d5e 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -226,18 +226,19 @@ int keeper_push_linda_storage(Universe* U, Dest L, void* ptr_, uintptr_t magic_) | |||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | // move data from keeper to destination state | 228 | // move data from keeper to destination state |
229 | lua_pushnil(KL); // storage nil | ||
230 | STACK_GROW(L, 5); | 229 | STACK_GROW(L, 5); |
231 | STACK_CHECK_START_REL(L, 0); | 230 | STACK_CHECK_START_REL(L, 0); |
232 | lua_newtable(L); // out | 231 | lua_newtable(L); // out |
232 | InterCopyContext c{ U, L, KL, {}, {}, {}, LookupMode::FromKeeper, {} }; | ||
233 | lua_pushnil(KL); // storage nil | ||
233 | while (lua_next(KL, -2)) // storage key fifo | 234 | while (lua_next(KL, -2)) // storage key fifo |
234 | { | 235 | { |
235 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl | 236 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl |
236 | lua_pushvalue(KL, -2); // storage key fifotbl key | 237 | lua_pushvalue(KL, -2); // storage key fifotbl key |
237 | std::ignore = luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key fifotbl // out key | 238 | std::ignore = c.inter_move(1); // storage key fifotbl // out key |
238 | STACK_CHECK(L, 2); | 239 | STACK_CHECK(L, 2); |
239 | lua_newtable(L); // out key keyout | 240 | lua_newtable(L); // out key keyout |
240 | std::ignore = luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key // out key keyout fifotbl | 241 | std::ignore = c.inter_move(1); // storage key // out key keyout fifotbl |
241 | lua_pushinteger(L, fifo->first); // out key keyout fifotbl first | 242 | lua_pushinteger(L, fifo->first); // out key keyout fifotbl first |
242 | STACK_CHECK(L, 5); | 243 | STACK_CHECK(L, 5); |
243 | lua_setfield(L, -3, "first"); // out key keyout fifotbl | 244 | lua_setfield(L, -3, "first"); // out key keyout fifotbl |
@@ -646,23 +647,24 @@ void close_keepers(Universe* U) | |||
646 | * Note: Any problems would be design flaws; the created Lua state is left | 647 | * Note: Any problems would be design flaws; the created Lua state is left |
647 | * unclosed, because it does not really matter. In production code, this | 648 | * unclosed, because it does not really matter. In production code, this |
648 | * function never fails. | 649 | * function never fails. |
649 | * settings table is at position 1 on the stack | 650 | * settings table is expected at position 1 on the stack |
650 | */ | 651 | */ |
651 | void init_keepers(Universe* U, lua_State* L) | 652 | void init_keepers(Universe* U, lua_State* L) |
652 | { | 653 | { |
654 | ASSERT_L(lua_gettop(L) == 1 && lua_istable(L, 1)); | ||
653 | STACK_CHECK_START_REL(L, 0); // L K | 655 | STACK_CHECK_START_REL(L, 0); // L K |
654 | lua_getfield(L, 1, "nb_keepers"); // nb_keepers | 656 | lua_getfield(L, 1, "nb_keepers"); // settings nb_keepers |
655 | int const nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; | 657 | int const nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; |
656 | lua_pop(L, 1); // | 658 | lua_pop(L, 1); // settings |
657 | if (nb_keepers < 1) | 659 | if (nb_keepers < 1) |
658 | { | 660 | { |
659 | luaL_error(L, "Bad number of keepers (%d)", nb_keepers); // doesn't return | 661 | luaL_error(L, "Bad number of keepers (%d)", nb_keepers); // doesn't return |
660 | } | 662 | } |
661 | STACK_CHECK(L, 0); | 663 | STACK_CHECK(L, 0); |
662 | 664 | ||
663 | lua_getfield(L, 1, "keepers_gc_threshold"); // keepers_gc_threshold | 665 | lua_getfield(L, 1, "keepers_gc_threshold"); // settings keepers_gc_threshold |
664 | int const keepers_gc_threshold{ static_cast<int>(lua_tointeger(L, -1)) }; | 666 | int const keepers_gc_threshold{ static_cast<int>(lua_tointeger(L, -1)) }; |
665 | lua_pop(L, 1); // | 667 | lua_pop(L, 1); // settings |
666 | STACK_CHECK(L, 0); | 668 | STACK_CHECK(L, 0); |
667 | 669 | ||
668 | // Keepers contains an array of 1 Keeper, adjust for the actual number of keeper states | 670 | // Keepers contains an array of 1 Keeper, adjust for the actual number of keeper states |
@@ -682,7 +684,7 @@ void init_keepers(Universe* U, lua_State* L) | |||
682 | U->keepers->keeper_array[i].Keeper::Keeper(); | 684 | U->keepers->keeper_array[i].Keeper::Keeper(); |
683 | } | 685 | } |
684 | } | 686 | } |
685 | for (int i = 0; i < nb_keepers; ++i) // keepersUD | 687 | for (int i = 0; i < nb_keepers; ++i) // settings |
686 | { | 688 | { |
687 | // note that we will leak K if we raise an error later | 689 | // note that we will leak K if we raise an error later |
688 | lua_State* const K{ create_state(U, L) }; | 690 | lua_State* const K{ create_state(U, L) }; |
@@ -706,26 +708,28 @@ void init_keepers(Universe* U, lua_State* L) | |||
706 | 708 | ||
707 | // make sure 'package' is initialized in keeper states, so that we have require() | 709 | // make sure 'package' is initialized in keeper states, so that we have require() |
708 | // this because this is needed when transferring deep userdata object | 710 | // this because this is needed when transferring deep userdata object |
709 | luaL_requiref(K, "package", luaopen_package, 1); // package | 711 | luaL_requiref(K, "package", luaopen_package, 1); // settings package |
710 | lua_pop(K, 1); // | 712 | lua_pop(K, 1); // settings |
711 | STACK_CHECK(K, 0); | 713 | STACK_CHECK(K, 0); |
712 | serialize_require(DEBUGSPEW_PARAM_COMMA(U) K); | 714 | serialize_require(DEBUGSPEW_PARAM_COMMA(U) K); |
713 | STACK_CHECK(K, 0); | 715 | STACK_CHECK(K, 0); |
714 | 716 | ||
715 | // copy package.path and package.cpath from the source state | 717 | // copy package.path and package.cpath from the source state (TODO: use _R._LOADED.package instead of _G.package) |
716 | lua_getglobal(L, "package"); // "..." keepersUD package | 718 | lua_getglobal(L, "package"); // settings package |
717 | if (!lua_isnil(L, -1)) | 719 | if (!lua_isnil(L, -1)) |
718 | { | 720 | { |
719 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately | 721 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately |
720 | if (luaG_inter_copy_package(U, Source{ L }, Dest{ K }, -1, LookupMode::ToKeeper) != InterCopyResult::Success) | 722 | InterCopyContext c{ U, Dest{ K }, Source{ L }, {}, SourceIndex{ lua_absindex(L, -1) }, {}, LookupMode::ToKeeper, {} }; |
723 | if (c.inter_copy_package() != InterCopyResult::Success) | ||
721 | { | 724 | { |
722 | // if something went wrong, the error message is at the top of the stack | 725 | // if something went wrong, the error message is at the top of the stack |
723 | lua_remove(L, -2); // error_msg | 726 | lua_remove(L, -2); // settings error_msg |
724 | raise_lua_error(L); | 727 | raise_lua_error(L); |
725 | } | 728 | } |
726 | } | 729 | } |
727 | lua_pop(L, 1); // | 730 | lua_pop(L, 1); // settings |
728 | STACK_CHECK(L, 0); | 731 | STACK_CHECK(L, 0); |
732 | STACK_CHECK(K, 0); | ||
729 | 733 | ||
730 | // attempt to call on_state_create(), if we have one and it is a C function | 734 | // attempt to call on_state_create(), if we have one and it is a C function |
731 | // (only support a C function because we can't transfer executable Lua code in keepers) | 735 | // (only support a C function because we can't transfer executable Lua code in keepers) |
@@ -837,20 +841,23 @@ KeeperCallResult keeper_call(Universe* U, lua_State* K, keeper_api_t func_, lua_ | |||
837 | ASSERT_L(lua_gettop(K) == 0); | 841 | ASSERT_L(lua_gettop(K) == 0); |
838 | 842 | ||
839 | STACK_GROW(K, 2); | 843 | STACK_GROW(K, 2); |
840 | 844 | PUSH_KEEPER_FUNC(K, func_); // func_ | |
841 | PUSH_KEEPER_FUNC(K, func_); // func_ | 845 | lua_pushlightuserdata(K, linda); // func_ linda |
842 | 846 | if ( | |
843 | lua_pushlightuserdata(K, linda); // func_ linda | 847 | (args == 0) || |
844 | 848 | (InterCopyContext{ U, Dest{ K }, Source{ L }, {}, {}, {}, LookupMode::ToKeeper, {} }.inter_copy(args) == InterCopyResult::Success) | |
845 | if ((args == 0) || luaG_inter_copy(U, Source{ L }, Dest{ K }, args, LookupMode::ToKeeper) == InterCopyResult::Success) // func_ linda args... | 849 | ) |
846 | { | 850 | { // func_ linda args... |
847 | lua_call(K, 1 + args, LUA_MULTRET); // result... | 851 | lua_call(K, 1 + args, LUA_MULTRET); // result... |
848 | int const retvals{ lua_gettop(K) - top_K }; | 852 | int const retvals{ lua_gettop(K) - top_K }; |
849 | // note that this can raise a luaL_error while the keeper state (and its mutex) is acquired | 853 | // note that this can raise a luaL_error while the keeper state (and its mutex) is acquired |
850 | // this may interrupt a lane, causing the destruction of the underlying OS thread | 854 | // this may interrupt a lane, causing the destruction of the underlying OS thread |
851 | // after this, another lane making use of this keeper can get an error code from the mutex-locking function | 855 | // after this, another lane making use of this keeper can get an error code from the mutex-locking function |
852 | // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) | 856 | // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) |
853 | if ((retvals == 0) || (luaG_inter_move(U, Source{ K }, Dest{ L }, retvals, LookupMode::FromKeeper) == InterCopyResult::Success)) // K->L | 857 | if ( |
858 | (retvals == 0) || | ||
859 | (InterCopyContext{ U, Dest{ L }, Source{ K }, {}, {}, {}, LookupMode::FromKeeper, {} }.inter_move(retvals) == InterCopyResult::Success) | ||
860 | ) // K->L | ||
854 | { | 861 | { |
855 | result.emplace(retvals); | 862 | result.emplace(retvals); |
856 | } | 863 | } |