improve an NodeRootLambda interface on LuaJIT
This commit is contained in:
parent
f96188ef14
commit
5c84d95139
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user