diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/llluamanager.cpp | 107 | ||||
-rw-r--r-- | indra/newview/llluamanager.h | 25 |
2 files changed, 76 insertions, 56 deletions
diff --git a/indra/newview/llluamanager.cpp b/indra/newview/llluamanager.cpp index 44c7a6ba3b..fac66003a1 100644 --- a/indra/newview/llluamanager.cpp +++ b/indra/newview/llluamanager.cpp @@ -64,13 +64,13 @@ lua_function(sleep) return 0; }; -/* // This function consumes ALL Lua stack arguments and returns concatenated // message string -std::string lua_print_msg_args(lua_State* L, const std::string_view& level) +std::string lua_print_msg(lua_State* L, const std::string_view& level) { - // On top of existing Lua arguments, push 'where' info - luaL_checkstack(L, 1, nullptr); + // On top of existing Lua arguments, we're going to push tostring() and + // duplicate each existing stack entry so we can stringize each one. + luaL_checkstack(L, 2, nullptr); luaL_where(L, 1); // start with the 'where' info at the top of the stack std::ostringstream out; @@ -79,7 +79,7 @@ std::string lua_print_msg_args(lua_State* L, const std::string_view& level) const char* sep = ""; // 'where' info ends with ": " // now iterate over arbitrary args, calling Lua tostring() on each and // concatenating with separators - for (int p = 1; p <= lua_gettop(L); ++p) + for (int p = 1, top = lua_gettop(L); p <= top; ++p) { out << sep; sep = " "; @@ -87,15 +87,15 @@ std::string lua_print_msg_args(lua_State* L, const std::string_view& level) // lua_tostring()! lua_getglobal(L, "tostring"); // Now the stack is arguments 1 .. N, plus tostring(). - // Rotate downwards, producing stack args 2 .. N, tostring(), arg1. - lua_rotate(L, 1, -1); - // pop tostring() and arg1, pushing tostring(arg1) + // Push a copy of the argument at index p. + lua_pushvalue(L, p); + // pop tostring() and arg-p, pushing tostring(arg-p) // (ignore potential error code from lua_pcall() because, if there was // an error, we expect the stack top to be an error message -- which // we'll print) lua_pcall(L, 1, 1, 0); - // stack now holds args 2 .. N, tostring(arg1) out << lua_tostring(L, -1); + lua_pop(L, 1); } // pop everything lua_settop(L, 0); @@ -105,20 +105,6 @@ std::string lua_print_msg_args(lua_State* L, const std::string_view& level) LLEventPumps::instance().obtain("lua output").post(stringize(level, ": ", msg)); return msg; } -*/ - -std::string lua_print_msg(lua_State *L, const std::string_view &level) -{ - lua_getglobal(L, "tostring"); - - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, 1); /* value to print */ - lua_call(L, 1, 1); - std::string msg = lua_tostring(L, -1); - - LLEventPumps::instance().obtain("lua output").post(stringize(level, ": ", msg)); - return msg; -} lua_function(print_debug) { @@ -187,19 +173,24 @@ lua_function(listen_events) } luaL_checkstack(L, 2, nullptr); +/*==========================================================================*| // Get the lua_State* for the main thread of this state, in case we were // called from a coroutine thread. We're going to make callbacks into Lua // code, and we want to do it on the main thread rather than a (possibly // suspended) coroutine thread. // Registry table is at pseudo-index LUA_REGISTRYINDEX // Main thread is at registry key LUA_RIDX_MAINTHREAD - auto regtype {lua_rawgeti(L, LUA_REGISTRYINDEX, 1 /*LUA_RIDX_MAINTHREAD*/)}; + auto regtype {lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD)}; // Not finding the main thread at the documented place isn't a user error, // it's a Problem llassert_always(regtype == LUA_TTHREAD); lua_State* mainthread{ lua_tothread(L, -1) }; // pop the main thread lua_pop(L, 1); +|*==========================================================================*/ + // Luau is based on Lua 5.1, and Lua 5.1 apparently provides no way to get + // back to the main thread from a coroutine thread? + lua_State* mainthread{ L }; luaL_checkstack(mainthread, 1, nullptr); LuaListener::ptr_t listener; @@ -284,14 +275,21 @@ void LLLUAmanager::runScriptFile(const std::string& filename, script_result_fn c runScriptFile(L, filename, cb); } -std::pair<int, LLSD> LLLUAmanager::waitScriptFile(LuaState& L, const std::string& filename) +LLCoros::Future<std::pair<int, LLSD>> +LLLUAmanager::startScriptFile(LuaState& L, const std::string& filename) { - LLCoros::Promise<std::pair<int, LLSD>> promise; - auto future{ LLCoros::getFuture(promise) }; + // Despite returning from startScriptFile(), we need this Promise to + // remain alive until the callback has fired. + auto promise{ std::make_shared<LLCoros::Promise<std::pair<int, LLSD>>>() }; runScriptFile(L, filename, - [&promise](int count, LLSD result) - { promise.set_value({ count, result }); }); - return future.get(); + [promise](int count, LLSD result) + { promise->set_value({ count, result }); }); + return LLCoros::getFuture(*promise); +} + +std::pair<int, LLSD> LLLUAmanager::waitScriptFile(LuaState& L, const std::string& filename) +{ + return startScriptFile(L, filename).get(); } void LLLUAmanager::runScriptFile(LuaState& L, const std::string& filename, script_result_fn cb) @@ -324,46 +322,53 @@ void LLLUAmanager::runScriptFile(LuaState& L, const std::string& filename, scrip }); } -void LLLUAmanager::runScriptLine(const std::string& cmd, script_finished_fn cb) +void LLLUAmanager::runScriptLine(const std::string& chunk, script_finished_fn cb) { // A script_finished_fn is used to initialize the LuaState. // It will be called when the LuaState is destroyed. LuaState L(cb); - runScriptLine(L, cmd); + runScriptLine(L, chunk); } -void LLLUAmanager::runScriptLine(const std::string& cmd, script_result_fn cb) +void LLLUAmanager::runScriptLine(const std::string& chunk, script_result_fn cb) { LuaState L; // A script_result_fn will be called when LuaState::expr() completes. - runScriptLine(L, cmd, cb); + runScriptLine(L, chunk, cb); +} + +LLCoros::Future<std::pair<int, LLSD>> +LLLUAmanager::startScriptLine(LuaState& L, const std::string& chunk) +{ + // Despite returning from startScriptLine(), we need this Promise to + // remain alive until the callback has fired. + auto promise{ std::make_shared<LLCoros::Promise<std::pair<int, LLSD>>>() }; + runScriptLine(L, chunk, + [promise](int count, LLSD result) + { promise->set_value({ count, result }); }); + return LLCoros::getFuture(*promise); } -std::pair<int, LLSD> LLLUAmanager::waitScriptLine(LuaState& L, const std::string& cmd) +std::pair<int, LLSD> LLLUAmanager::waitScriptLine(LuaState& L, const std::string& chunk) { - LLCoros::Promise<std::pair<int, LLSD>> promise; - auto future{ LLCoros::getFuture(promise) }; - runScriptLine(L, cmd, - [&promise](int count, LLSD result) - { promise.set_value({ count, result }); }); - return future.get(); + return startScriptLine(L, chunk).get(); } -void LLLUAmanager::runScriptLine(LuaState& L, const std::string& cmd, script_result_fn cb) +void LLLUAmanager::runScriptLine(LuaState& L, const std::string& chunk, script_result_fn cb) { - // find a suitable abbreviation for the cmd string - std::string_view shortcmd{ cmd }; + // find a suitable abbreviation for the chunk string + std::string shortchunk{ chunk }; const size_t shortlen = 40; - std::string::size_type eol = shortcmd.find_first_of("\r\n"); + std::string::size_type eol = shortchunk.find_first_of("\r\n"); if (eol != std::string::npos) - shortcmd = shortcmd.substr(0, eol); - if (shortcmd.length() > shortlen) - shortcmd = stringize(shortcmd.substr(0, shortlen), "..."); + shortchunk = shortchunk.substr(0, eol); + if (shortchunk.length() > shortlen) + shortchunk = stringize(shortchunk.substr(0, shortlen), "..."); - std::string desc{ stringize("runScriptLine('", shortcmd, "')") }; - LLCoros::instance().launch(desc, [&L, desc, cmd, cb]() + std::string desc{ stringize("runScriptLine('", shortchunk, "')") }; + LLCoros::instance().launch(desc, [&L, desc, chunk, cb]() { - auto [count, result] = L.expr(desc, cmd); + auto [count, result] = L.expr(desc, chunk); if (cb) { cb(count, result); diff --git a/indra/newview/llluamanager.h b/indra/newview/llluamanager.h index bed12e358a..12284cd0e4 100644 --- a/indra/newview/llluamanager.h +++ b/indra/newview/llluamanager.h @@ -27,6 +27,7 @@ #ifndef LL_LLLUAMANAGER_H #define LL_LLLUAMANAGER_H +#include "llcoros.h" #include "llsd.h" #include <functional> #include <string> @@ -52,16 +53,30 @@ public: static void runScriptFile(const std::string &filename, script_finished_fn cb = {}); static void runScriptFile(const std::string &filename, script_result_fn cb); static void runScriptFile(LuaState& L, const std::string &filename, script_result_fn cb = {}); + // Start running a Lua script file, returning an LLCoros::Future whose + // get() method will pause the calling coroutine until it can deliver the + // (count, result) pair described above. Between startScriptFile() and + // Future::get(), the caller and the Lua script coroutine will run + // concurrently. + static LLCoros::Future<std::pair<int, LLSD>> + startScriptFile(LuaState& L, const std::string& filename); // Run a Lua script file, and pause the calling coroutine until it completes. // The return value is the (count, result) pair described above. static std::pair<int, LLSD> waitScriptFile(LuaState& L, const std::string& filename); - static void runScriptLine(const std::string &cmd, script_finished_fn cb = {}); - static void runScriptLine(const std::string &cmd, script_result_fn cb); - static void runScriptLine(LuaState& L, const std::string &cmd, script_result_fn cb = {}); - // Run a Lua expression string, and pause the calling coroutine until it completes. + static void runScriptLine(const std::string &chunk, script_finished_fn cb = {}); + static void runScriptLine(const std::string &chunk, script_result_fn cb); + static void runScriptLine(LuaState& L, const std::string &chunk, script_result_fn cb = {}); + // Start running a Lua chunk, returning an LLCoros::Future whose + // get() method will pause the calling coroutine until it can deliver the + // (count, result) pair described above. Between startScriptLine() and + // Future::get(), the caller and the Lua script coroutine will run + // concurrently. + static LLCoros::Future<std::pair<int, LLSD>> + startScriptLine(LuaState& L, const std::string& chunk); + // Run a Lua chunk, and pause the calling coroutine until it completes. // The return value is the (count, result) pair described above. - static std::pair<int, LLSD> waitScriptLine(LuaState& L, const std::string& cmd); + static std::pair<int, LLSD> waitScriptLine(LuaState& L, const std::string& chunk); static void runScriptOnLogin(); }; |