improve an NodeRootLambda interface on LuaJIT

This commit is contained in:
falsycat 2022-09-30 17:33:04 +09:00
parent f96188ef14
commit 5c84d95139
4 changed files with 60 additions and 61 deletions

View File

@ -341,15 +341,59 @@ void PushMutableVector(lua_State* L, std::vector<uint8_t>&& v) noexcept {
void PushNodeRootLambda(
lua_State* L, const std::shared_ptr<nf7::NodeRootLambda>& la) noexcept {
constexpr const char* kTypeName = "nf7::NodeRootLambda";
assert(la);
using T = std::shared_ptr<nf7::NodeRootLambda>;
new (lua_newuserdata(L, sizeof(T))) T {la};
if (luaL_newmetatable(L, kTypeName)) {
if (luaL_newmetatable(L, "nf7::NodeRootLambda")) {
lua_createtable(L, 0, 0);
{
// la:send(nf7, key, value)
lua_pushcfunction(L, [](auto L) {
auto la = CheckNodeRootLambda(L, 1);
la->ExecSend(luaL_checkstring(L, 2), luajit::CheckValue(L, 3));
return 0;
});
lua_setfield(L, -2, "send");
// la:recv(nf7, {name1, name2, ...})
lua_pushcfunction(L, [](auto L) {
auto la = CheckNodeRootLambda(L, 1);
auto th = luajit::Thread::GetPtr(L, 2);
std::vector<std::string> names;
ToStringList(L, 3, names);
if (names.size() == 0) {
return 0;
}
auto fu = la->Select(
std::unordered_set<std::string>(names.begin(), names.end()));
if (fu.done()) {
try {
const auto& p = fu.value();
lua_pushstring(L, p.first.c_str());
luajit::PushValue(L, p.second);
return 2;
} catch (nf7::Exception&) {
return 0;
}
} else {
fu.ThenIf([L, th](auto& p) {
th->ExecResume(L, p.first, p.second);
}).template Catch<nf7::Exception>(nullptr, [L, th](nf7::Exception&) {
th->ExecResume(L);
});
return th->Yield(L);
}
});
lua_setfield(L, -2, "recv");
}
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, [](auto L) {
CheckRef<T>(L, 1, kTypeName).~T();
CheckNodeRootLambda(L, 1).~T();
return 0;
});
lua_setfield(L, -2, "__gc");

View File

@ -73,8 +73,15 @@ inline const std::shared_ptr<nf7::NodeRootLambda>& CheckNodeRootLambda(lua_State
}
inline void ToStringList(lua_State* L, int idx, std::vector<std::string>& v) noexcept {
const size_t n = lua_objlen(L, idx);
v.clear();
if (!lua_istable(L, idx)) {
if (auto str = lua_tostring(L, idx)) {
v.emplace_back(str);
}
return;
}
const size_t n = lua_objlen(L, idx);
v.reserve(n);
for (int i = 1; i <= static_cast<int>(n); ++i) {
lua_rawgeti(L, idx, i);

View File

@ -141,7 +141,7 @@ static void PushMeta(lua_State* L) noexcept {
th->ExecResume(L, 0);
}
});
return th->Yield(L, 0);
return th->Yield(L);
});
lua_setfield(L, -2, "resolve");
@ -176,7 +176,7 @@ static void PushMeta(lua_State* L) noexcept {
th->ExecResume(L, nullptr, e.msg());
}
});
return th->Yield(L, 0);
return th->Yield(L);
});
lua_setfield(L, -2, "query");
@ -189,62 +189,10 @@ static void PushMeta(lua_State* L) noexcept {
std::chrono::milliseconds(static_cast<uint64_t>(sec*1000));
th->ljq()->Push(th->ctx(), [th, L](auto) { th->ExecResume(L); }, time);
return th->Yield(L, 0);
return th->Yield(L);
});
lua_setfield(L, -2, "sleep");
// nf7:send(obj, params...)
lua_pushcfunction(L, [](auto L) {
auto th = Thread::GetPtr(L, 1);
auto la = luajit::CheckNodeRootLambda(L, 2);
la->ExecSend(luaL_checkstring(L, 3), luajit::CheckValue(L, 4));
return 0;
});
lua_setfield(L, -2, "send");
// nf7:recv(obj, params...)
lua_pushcfunction(L, [](auto L) {
auto th = Thread::GetPtr(L, 1);
auto la = luajit::CheckNodeRootLambda(L, 2);
std::unordered_set<std::string> names;
if (lua_istable(L, 3)) {
lua_pushnil(L);
while (lua_next(L, 3)) {
if (lua_isstring(L, -1)) {
names.insert(lua_tostring(L, -1));
} else {
return luaL_error(L, "table contains non-string value");
}
lua_pop(L, 1);
}
} else {
for (int i = 3; i <= lua_gettop(L); ++i) {
names.insert(luaL_checkstring(L, i));
}
}
auto fu = la->Select(std::move(names));
if (fu.done()) {
try {
const auto& p = fu.value();
lua_pushstring(L, p.first.c_str());
luajit::PushValue(L, p.second);
return 2;
} catch (nf7::Exception& e) {
return 0;
}
} else {
fu.ThenIf([L, th](auto& p) {
th->ExecResume(L, p.first, p.second);
}).template Catch<nf7::Exception>(nullptr, [L, th](nf7::Exception&) {
th->ExecResume(L);
});
return th->Yield(L, 0);
}
});
lua_setfield(L, -2, "recv");
// nf7:yield(results...)
lua_pushcfunction(L, [](auto L) {
return lua_yield(L, lua_gettop(L)-1);

View File

@ -84,9 +84,9 @@ class Thread final : public std::enable_shared_from_this<Thread> {
// must be called on luajit thread
// handler_ won't be called on this yielding
int Yield(lua_State* L, int narg) {
int Yield(lua_State* L) {
skip_handle_ = true;
return lua_yield(L, narg);
return lua_yield(L, 0);
}
// must be called on luajit thread