tangible.start version 2: multistart

This commit is contained in:
2022-05-16 15:17:08 -04:00
parent cbb074011d
commit 3b805c3e8a
2 changed files with 69 additions and 63 deletions

View File

@@ -297,7 +297,9 @@ LuaDefine(tangible_start, "tangible,function,arg1,arg2...",
"|" "|"
"|Every thread is owned by a tangible. The first argument" "|Every thread is owned by a tangible. The first argument"
"|to 'tangible.start' indicates the tangible that owns" "|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." "|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" "|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; int varlen = top - 2;
World *w = World::fetch_global_pointer(L); 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; LuaVar mt, classtab, plthreads, thread, thinfo, func, tanlist;
LuaStack LS(L, mt, classtab, plthreads, thread, thinfo); LuaStack LS(L, mt, classtab, plthreads, thread, thinfo, func, tanlist);
LuaSpecial place(1); LuaSpecial place(1);
LuaSpecial func(2); LuaSpecial fname(2);
// Confirm that the place is a valid tangible, // If they passed in a single tangible, convert it to a tangible list.
// and get the tangible ID.
w->tangible_get(LS, place);
int64_t place_id = LS.tanid(place); int64_t place_id = LS.tanid(place);
if (place_id != 0) {
// Get place's metatable. LS.newtable(tanlist);
LS.getmetatable(mt, place); LS.rawset(tanlist, 1, place);
if (!LS.istable(mt)) { } else {
luaL_error(L, "invalid tangible passed to tangible.start"); LS.set(tanlist, place);
return 0; if (!LS.istable(tanlist)) {
} luaL_error(L, "tangible.start expects a tangible or list of tangibles");
// 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");
return 0; return 0;
} }
} }
// Get a thread ID for the new thread for (int i = 1; ; i++) {
int64_t tid = w->alloc_id_predictable(); LS.rawget(place, tanlist, i);
if (LS.isnil(place)) break;
// Create a new thread, set up function and arguments. // Confirm that the place is a valid tangible,
lua_State *CO = LS.newthread(thread); // and get the tangible ID.
lua_pushvalue(L, func.index()); w->tangible_get(LS, place);
for (int i = 0; i < varlen; i++) { place_id = LS.tanid(place);
lua_pushvalue(L, i + 3);
// 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(); return LS.result();
} }

View File

@@ -299,9 +299,6 @@ private:
// //
static void store_global_pointer(lua_State *L, World *w); 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. // Invoke a plan.
// //
void invoke_plan(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data); void invoke_plan(int64_t actor_id, int64_t place_id, const eng::string &action, const InvocationData &data);