Lua: Be more strict with concurrency and multiple contexts.

This commit is contained in:
Vas Crabb 2023-03-08 04:09:22 +11:00
parent 6dea565343
commit f2a5f52526
2 changed files with 29 additions and 16 deletions

View File

@ -45,8 +45,8 @@ function console.startplugin()
function(c, str)
status = str
yield()
for k, v in pairs(status) do
ln.addcompletion(c, v)
for candidate in status:gmatch('([^\001]+)') do
ln.addcompletion(c, candidate)
end
end)
local ret = ln.linenoise('$PROMPT')
@ -207,9 +207,9 @@ function console.startplugin()
local str, strs, expr, sep = simplify_expression(line, word)
contextual_list(expr, sep, str, word, strs)
if #matches == 0 then
return { line }
return line
elseif #matches == 1 then
return { start .. matches[1] }
return start .. matches[1]
end
print("")
result = { }
@ -217,7 +217,7 @@ function console.startplugin()
print(v)
table.insert(result, start .. v)
end
return result
return table.concat(result, '\001')
end
emu.register_start(function()

View File

@ -63,7 +63,7 @@ namespace {
struct thread_context
{
private:
sol::object m_result;
std::string m_result;
std::mutex m_guard;
std::condition_variable m_sync;
@ -73,7 +73,7 @@ public:
bool start(char const *scr)
{
std::unique_lock<std::mutex> lock(m_guard);
std::unique_lock<std::mutex> caller_lock(m_guard);
if (m_busy)
return false;
@ -87,6 +87,7 @@ public:
thstate["package"]["preload"]["lfs"] = &luaopen_lfs;
thstate["package"]["preload"]["linenoise"] = &luaopen_linenoise;
sol::load_result res = thstate.load(script);
std::unique_lock<std::mutex> result_lock(m_guard, std::defer_lock);
if (res.valid())
{
sol::protected_function func = res.get<sol::protected_function>();
@ -94,17 +95,24 @@ public:
"yield",
[this, &thstate]()
{
std::unique_lock<std::mutex> lock(m_guard);
std::unique_lock<std::mutex> yield_lock(m_guard);
m_result = thstate["status"];
m_yield = true;
m_sync.wait(lock);
m_sync.wait(yield_lock);
m_yield = false;
thstate["status"] = m_result;
});
auto ret = func();
result_lock.lock();
if (ret.valid())
{
m_result = ret.get<sol::object>();
auto result = ret.get<std::optional<char const *> >();
if (!result)
osd_printf_error("[LUA ERROR] in thread: return value must be string\n");
else if (!*result)
m_result.clear();
else
m_result = *result;
}
else
{
@ -114,10 +122,12 @@ public:
}
else
{
result_lock.lock();
sol::error err = res;
osd_printf_error("[LUA ERROR] when loading script for thread: %s\n", err.what());
}
m_busy = false; // FIXME: shouldn't do this when not holding the lock
assert(result_lock);
m_busy = false;
});
m_busy = true;
m_yield = false;
@ -125,23 +135,26 @@ public:
return true;
}
void resume(sol::object val)
void resume(char const *val)
{
std::unique_lock<std::mutex> lock(m_guard);
if (m_yield)
{
m_result = val;
if (val)
m_result = val;
else
m_result.clear();
m_sync.notify_all();
}
}
sol::object result()
char const *result()
{
std::unique_lock<std::mutex> lock(m_guard);
if (m_busy && !m_yield)
return sol::lua_nil;
return "";
else
return m_result;
return m_result.c_str();
}
};