From 3b805c3e8a69a7be1afc351849c2eab8cb7d8518 Mon Sep 17 00:00:00 2001 From: jyelon Date: Mon, 16 May 2022 15:17:08 -0400 Subject: [PATCH] tangible.start version 2: multistart --- luprex/core/cpp/world-accessor.cpp | 129 +++++++++++++++-------------- luprex/core/cpp/world.hpp | 3 - 2 files changed, 69 insertions(+), 63 deletions(-) diff --git a/luprex/core/cpp/world-accessor.cpp b/luprex/core/cpp/world-accessor.cpp index da680435..d9509e3a 100644 --- a/luprex/core/cpp/world-accessor.cpp +++ b/luprex/core/cpp/world-accessor.cpp @@ -297,7 +297,9 @@ LuaDefine(tangible_start, "tangible,function,arg1,arg2...", "|" "|Every thread is owned by a tangible. The first argument" "|to 'tangible.start' indicates the tangible that owns" - "|the new thread." + "|the new thread. Instead of passing a single tangible," + "|you can pass a list of tangibles, in which case a thread" + "|is started on each tangible." "|" "|The function can be a lua closure, or it can be a string." "|If it's a string, then the tangible's class will be" @@ -341,75 +343,82 @@ LuaDefine(tangible_start, "tangible,function,arg1,arg2...", int varlen = top - 2; World *w = World::fetch_global_pointer(L); - w->guard_nopredict(L, "tangible.start"); + w->guard_blockable(L, "tangible.start"); - LuaVar mt, classtab, plthreads, thread, thinfo; - LuaStack LS(L, mt, classtab, plthreads, thread, thinfo); + LuaVar mt, classtab, plthreads, thread, thinfo, func, tanlist; + LuaStack LS(L, mt, classtab, plthreads, thread, thinfo, func, tanlist); LuaSpecial place(1); - LuaSpecial func(2); + LuaSpecial fname(2); - // Confirm that the place is a valid tangible, - // and get the tangible ID. - w->tangible_get(LS, place); + // If they passed in a single tangible, convert it to a tangible list. int64_t place_id = LS.tanid(place); - - // Get place's metatable. - LS.getmetatable(mt, place); - if (!LS.istable(mt)) { - luaL_error(L, "invalid tangible passed to tangible.start"); - return 0; - } - - // Get place's threads table. - LS.rawget(plthreads, mt, "threads"); - if (!LS.istable(plthreads)) { - luaL_error(L, "invalid tangible passed to tangible.start"); - return 0; - } - - // If the function is actually a function-name, - // then convert it to a closure. - if (!LS.isfunction(func)) { - if (!LS.isstring(func)) { - luaL_error(L, "invalid function passed to tangible.start"); - return 0; - } - LS.rawget(classtab, mt, "__index"); - if (!LS.istable(classtab)) { - luaL_error(L, "tangible doesn't have a class table in tangible.start"); - return 0; - } - LS.rawget(func, classtab, func); - if (!LS.isfunction(func)) { - luaL_error(L, "tangible doesn't have specified method in tangible.start"); + if (place_id != 0) { + LS.newtable(tanlist); + LS.rawset(tanlist, 1, place); + } else { + LS.set(tanlist, place); + if (!LS.istable(tanlist)) { + luaL_error(L, "tangible.start expects a tangible or list of tangibles"); return 0; } } - // Get a thread ID for the new thread - int64_t tid = w->alloc_id_predictable(); + for (int i = 1; ; i++) { + LS.rawget(place, tanlist, i); + if (LS.isnil(place)) break; - // Create a new thread, set up function and arguments. - lua_State *CO = LS.newthread(thread); - lua_pushvalue(L, func.index()); - for (int i = 0; i < varlen; i++) { - lua_pushvalue(L, i + 3); + // Confirm that the place is a valid tangible, + // and get the tangible ID. + w->tangible_get(LS, place); + place_id = LS.tanid(place); + + // Get place's metatable and threads table. + LS.getmetatable(mt, place); + assert(LS.istable(mt)); + LS.rawget(plthreads, mt, "threads"); + assert(LS.istable(plthreads)); + + // Get the function closure. + if (LS.isfunction(fname)) { + LS.set(func, fname); + } else if (LS.isstring(fname)) { + LS.rawget(classtab, mt, "__index"); + assert(LS.istable(classtab)); + LS.rawget(func, classtab, fname); + if (!LS.isfunction(func)) { + eng::string cfname = LS.ckstring(fname); + luaL_error(L, "tangible doesn't have method: %s", cfname.c_str()); + return 0; + } + } else { + luaL_error(L, "invalid function, expected closure or string"); + return 0; + } + + // Create a new thread, set up function and arguments. + lua_State *CO = LS.newthread(thread); + lua_pushvalue(L, func.index()); + for (int i = 0; i < varlen; i++) { + lua_pushvalue(L, i + 3); + } + lua_xmove(L, CO, varlen + 1); + + // Create the thread info table. + LS.newtable(thinfo); + LS.rawset(thinfo, "thread", thread); + LS.rawset(thinfo, "actorid", w->lthread_actor_id_); + LS.rawset(thinfo, "isnew", true); + LS.rawset(thinfo, "useppool", false); + LS.rawset(thinfo, "print", false); + + // Get a thread ID for the new thread, store it in + // the thread table. + int64_t tid = w->alloc_id_predictable(); + LS.rawset(plthreads, tid, thinfo); + + // Push the thread's ID into the runnable thread queue. + w->schedule(0, tid, place_id); } - lua_xmove(L, CO, varlen + 1); - - // Create the thread info table. - LS.newtable(thinfo); - LS.rawset(thinfo, "thread", thread); - LS.rawset(thinfo, "actorid", w->lthread_actor_id_); - LS.rawset(thinfo, "isnew", true); - LS.rawset(thinfo, "useppool", false); - LS.rawset(thinfo, "print", false); - - LS.rawset(plthreads, tid, thinfo); - LS.result(); - - // Push the thread's ID into the runnable thread queue. - w->schedule(0, tid, place_id); return LS.result(); } diff --git a/luprex/core/cpp/world.hpp b/luprex/core/cpp/world.hpp index 4eac0ca4..cb562538 100644 --- a/luprex/core/cpp/world.hpp +++ b/luprex/core/cpp/world.hpp @@ -299,9 +299,6 @@ private: // static void store_global_pointer(lua_State *L, World *w); - // Start a thread on the specified tangible. - void tangible_start(Tangible *actor, Tangible *place, LuaStack &LS, LuaSlot func, int argpos, int nargs); - // Invoke a plan. // void invoke_plan(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data);