diff --git a/luprex/core/cpp/world-accessor.cpp b/luprex/core/cpp/world-accessor.cpp index f7a31194..79e2e8dd 100644 --- a/luprex/core/cpp/world-accessor.cpp +++ b/luprex/core/cpp/world-accessor.cpp @@ -153,6 +153,21 @@ LuaDefine(tangible_id, "c") { return LS.result(); } +LuaDefine(tangible_getactor, "c") { + LuaRet actor; + LuaStack LS(L, actor); + LS.rawget(actor, LuaRegistry, "actor"); + return LS.result(); +} + +LuaDefine(tangible_getplace, "c") { + LuaRet place; + LuaStack LS(L, place); + LS.rawget(place, LuaRegistry, "place"); + return LS.result(); +} + + LuaDefine(world_wait, "f") { if ((lua_gettop(L) != 1) || (lua_type(L, -1) != LUA_TNUMBER)) { luaL_error(L, "Argument to wait must be a number."); diff --git a/luprex/core/cpp/world-core.cpp b/luprex/core/cpp/world-core.cpp index 93fb7310..82c60eb0 100644 --- a/luprex/core/cpp/world-core.cpp +++ b/luprex/core/cpp/world-core.cpp @@ -302,7 +302,11 @@ void World::update_gui(int64_t actor_id, int64_t place_id, Gui *gui) { lua_pushvalue(L, actor.index()); lua_pushvalue(L, place.index()); Gui::store_global_pointer(L, gui); + LS.rawset(LuaRegistry, "actor", actor); + LS.rawset(LuaRegistry, "place", place); int status = traceback_pcall(L, 2, 0); + LS.rawset(LuaRegistry, "actor", LuaNil); + LS.rawset(LuaRegistry, "place", LuaNil); Gui::store_global_pointer(L, nullptr); if (status != 0) { gui->clear(); @@ -361,8 +365,8 @@ void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &a // Set up for Lua manipulation. lua_State *L = state(); - LuaVar actor, place, func, tangibles, mt, index, actions, thread, threads, message, invdata; - LuaStack LS(L, actor, place, func, tangibles, mt, index, actions, thread, threads, message, invdata); + LuaVar actor, place, func, tangibles, mt, index, actions, thread, threads, thinfo, message, invdata; + LuaStack LS(L, actor, place, func, tangibles, mt, index, actions, thread, threads, thinfo, message, invdata); // Get the actor and place. LS.rawget(tangibles, LuaRegistry, "tangibles"); @@ -404,22 +408,26 @@ void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &a // Create a new thread, set up function and parameters. lua_State *CO = LS.newthread(thread); - // Push the function to be invoked and its arguments. + // Move function and args to new thread. lua_pushvalue(L, func.index()); lua_pushvalue(L, actor.index()); lua_pushvalue(L, place.index()); lua_pushvalue(L, invdata.index()); - - // Move actor, place, function and args to new thread. lua_xmove(L, CO, 4); + // Create the thread info table. + LS.newtable(thinfo); + LS.rawset(thinfo, "thread", thread); + LS.rawset(thinfo, "actor", actor); + LS.rawset(thinfo, "isnew", true); + // Store the thread into place's thread table. LS.rawget(threads, mt, "threads"); if (!LS.istable(threads)) { LS.result(); return; } - LS.rawset(threads, tid, thread); + LS.rawset(threads, tid, thinfo); LS.result(); // Push the thread's ID into the runnable thread queue, @@ -432,8 +440,8 @@ void World::invoke_plan(int64_t actor_id, int64_t place_id, const std::string &a void World::run_scheduled_threads(int64_t clk) { assert(stack_is_clear()); lua_State *L = state(); - LuaVar tangibles, place, mt, threads, thread; - LuaStack LS(L, tangibles, place, mt, threads, thread); + LuaVar tangibles, actor, place, mt, threads, thinfo, isnew, thread; + LuaStack LS(L, tangibles, actor, place, mt, threads, thinfo, isnew, thread); LS.rawget(tangibles, LuaRegistry, "tangibles"); while (thread_sched_.ready(clk)) { @@ -450,15 +458,31 @@ void World::run_scheduled_threads(int64_t clk) { if (!LS.istable(threads)) { continue; } - LS.rawget(thread, threads, sched.thread_id()); + LS.rawget(thinfo, threads, sched.thread_id()); + if (!LS.istable(thinfo)) { + continue; + } + LS.rawget(actor, thinfo, "actor"); + if (!LS.istable(actor)) { + continue; + } + LS.rawget(isnew, thinfo, "isnew"); + if (!LS.isboolean(isnew)) { + continue; + } + LS.rawget(thread, thinfo, "thread"); if (!LS.isthread(thread)) { continue; } // Resume the coroutine. + LS.rawset(thinfo, "isnew", false); lua_State *CO = LS.ckthread(thread); - int top = lua_gettop(CO); - int status = lua_resume(CO, nullptr, (top >= 4) ? 3 : 0); + LS.rawset(LuaRegistry, "actor", actor); + LS.rawset(LuaRegistry, "place", place); + int status = lua_resume(CO, nullptr, LS.ckboolean(isnew) ? 3 : 0); + LS.rawset(LuaRegistry, "actor", LuaNil); + LS.rawset(LuaRegistry, "place", LuaNil); // Three possible outcomes: finished, yielded, or errored. if (status == LUA_YIELD) {