aboutsummaryrefslogtreecommitdiff
path: root/src/keeper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/keeper.cpp')
-rw-r--r--src/keeper.cpp59
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 */
651void init_keepers(Universe* U, lua_State* L) 652void 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 }