replace to nf7:yield() from a custom type of Node::Lambda in Lua script
This commit is contained in:
@@ -368,43 +368,6 @@ void PushMutableVector(lua_State* L, std::vector<uint8_t>&& v) noexcept {
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
void PushNodeLambda(lua_State* L,
|
||||
const std::shared_ptr<nf7::Node::Lambda>& callee,
|
||||
const std::weak_ptr<nf7::Node::Lambda>& caller) noexcept {
|
||||
constexpr auto kTypeName = "nf7::Node::Lambda";
|
||||
struct Data {
|
||||
std::shared_ptr<nf7::Node::Lambda> callee;
|
||||
std::weak_ptr<nf7::Node::Lambda> caller;
|
||||
};
|
||||
new (lua_newuserdata(L, sizeof(Data))) Data { .callee = callee, .caller = caller };
|
||||
|
||||
if (luaL_newmetatable(L, kTypeName)) {
|
||||
lua_pushcfunction(L, [](auto L) {
|
||||
const auto& d = *reinterpret_cast<Data*>(luaL_checkudata(L, 1, kTypeName));
|
||||
|
||||
auto caller = d.caller.lock();
|
||||
if (!caller) return luaL_error(L, "caller expired");
|
||||
|
||||
std::string n = luaL_checkstring(L, 2);
|
||||
auto v = nf7::luajit::CheckValue(L, 3);
|
||||
|
||||
auto callee = d.callee;
|
||||
callee->env().ExecSub(callee, [callee, caller, n = std::move(n), v = std::move(v)]() {
|
||||
callee->Handle(n, v, caller);
|
||||
});
|
||||
return 0;
|
||||
});
|
||||
lua_setfield(L, -2, "__call");
|
||||
|
||||
lua_pushcfunction(L, [](auto L) {
|
||||
reinterpret_cast<Data*>(luaL_checkudata(L, 1, kTypeName))->~Data();
|
||||
return 0;
|
||||
});
|
||||
lua_setfield(L, -2, "__gc");
|
||||
}
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
|
||||
std::optional<nf7::Value> ToValue(lua_State* L, int idx) noexcept {
|
||||
if (lua_isnoneornil(L, idx)) {
|
||||
|
@@ -9,7 +9,6 @@
|
||||
|
||||
#include <lua.hpp>
|
||||
|
||||
#include "common/node.hh"
|
||||
#include "common/value.hh"
|
||||
|
||||
|
||||
@@ -20,9 +19,6 @@ void PushImmEnv(lua_State*) noexcept;
|
||||
void PushValue(lua_State*, const nf7::Value&) noexcept;
|
||||
void PushVector(lua_State*, const nf7::Value::ConstVector&) noexcept;
|
||||
void PushMutableVector(lua_State*, std::vector<uint8_t>&&) noexcept;
|
||||
void PushNodeLambda(lua_State*,
|
||||
const std::shared_ptr<nf7::Node::Lambda>& callee,
|
||||
const std::weak_ptr<nf7::Node::Lambda>& caller) noexcept;
|
||||
|
||||
std::optional<nf7::Value> ToValue(lua_State*, int) noexcept;
|
||||
std::optional<nf7::Value::ConstVector> ToVector(lua_State*, int) noexcept;
|
||||
|
@@ -147,9 +147,6 @@ static void PushMeta(lua_State* L) noexcept {
|
||||
|
||||
// nf7:yield(results...)
|
||||
lua_pushcfunction(L, [](auto L) {
|
||||
auto th = Thread::GetPtr(L, 1);
|
||||
th->ExecResume(L);
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, lua_gettop(L)-1);
|
||||
});
|
||||
lua_setfield(L, -2, "yield");
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -17,6 +18,7 @@
|
||||
#include "common/logger_ref.hh"
|
||||
#include "common/luajit.hh"
|
||||
#include "common/luajit_ref.hh"
|
||||
#include "common/node.hh"
|
||||
|
||||
|
||||
namespace nf7::luajit {
|
||||
@@ -40,9 +42,14 @@ class Thread final : public std::enable_shared_from_this<Thread> {
|
||||
|
||||
// Creates a handler to finalize a promise.
|
||||
template <typename T>
|
||||
static Handler CreatePromiseHandler(
|
||||
static inline Handler CreatePromiseHandler(
|
||||
nf7::Future<T>::Promise& pro, std::function<T(lua_State*)>&&) noexcept;
|
||||
|
||||
// Creates a handler to emit yielded value to Node::Lambda.
|
||||
static inline Handler CreateNodeLambdaHandler(
|
||||
const std::shared_ptr<nf7::Node::Lambda>& caller,
|
||||
const std::shared_ptr<nf7::Node::Lambda>& callee) noexcept;
|
||||
|
||||
// must be called on luajit thread
|
||||
static std::shared_ptr<Thread> GetPtr(lua_State* L, int idx) {
|
||||
auto th = CheckWeakPtr<Thread>(L, idx, kTypeName);
|
||||
@@ -176,4 +183,42 @@ Thread::Handler Thread::CreatePromiseHandler(
|
||||
};
|
||||
}
|
||||
|
||||
Thread::Handler Thread::CreateNodeLambdaHandler(
|
||||
const std::shared_ptr<nf7::Node::Lambda>& caller,
|
||||
const std::shared_ptr<nf7::Node::Lambda>& callee) noexcept {
|
||||
return [caller, callee](auto& th, auto L) {
|
||||
switch (th.state()) {
|
||||
case nf7::luajit::Thread::kPaused:
|
||||
switch (lua_gettop(L)) {
|
||||
case 0:
|
||||
th.ExecResume(L);
|
||||
return;
|
||||
case 2: {
|
||||
auto k = luaL_checkstring(L, 1);
|
||||
auto v = nf7::luajit::CheckValue(L, 2);
|
||||
caller->env().ExecSub(
|
||||
caller, [caller, callee, k = std::string {k}, v = std::move(v)]() {
|
||||
caller->Handle(k, v, callee);
|
||||
});
|
||||
} return;
|
||||
default:
|
||||
if (auto log = th.logger()) {
|
||||
log->Warn("invalid use of yield, nf7:yield() or nf7:yield(name, value)");
|
||||
}
|
||||
th.Resume(L, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
case nf7::luajit::Thread::kFinished:
|
||||
return;
|
||||
|
||||
default:
|
||||
if (auto log = th.logger()) {
|
||||
log->Warn(std::string {"luajit execution error: "}+lua_tostring(L, -1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace nf7::luajit
|
||||
|
@@ -138,7 +138,7 @@ class InlineNode::Lambda final : public nf7::Node::Lambda,
|
||||
auto self = shared_from_this();
|
||||
auto th = std::make_shared<nf7::luajit::Thread>(
|
||||
self, ljq,
|
||||
[self, ljq](auto& th, auto L) { self->HandleThread(ljq, th, L); });
|
||||
nf7::luajit::Thread::CreateNodeLambdaHandler(caller, shared_from_this()));
|
||||
th->Install(log_);
|
||||
th_.emplace_back(th);
|
||||
|
||||
@@ -165,7 +165,6 @@ class InlineNode::Lambda final : public nf7::Node::Lambda,
|
||||
// push args
|
||||
lua_pushstring(thL, p.first.c_str()); // key
|
||||
nf7::luajit::PushValue(thL, p.second); // value
|
||||
nf7::luajit::PushNodeLambda(thL, caller, self); // caller
|
||||
|
||||
// push ctx table
|
||||
if (ctxtable_ && ctxtable_->ljq() != ljq) {
|
||||
@@ -181,7 +180,7 @@ class InlineNode::Lambda final : public nf7::Node::Lambda,
|
||||
}
|
||||
|
||||
// start function
|
||||
th->Resume(thL, 4);
|
||||
th->Resume(thL, 3);
|
||||
});
|
||||
|
||||
} catch (nf7::LifeExpiredException&) {
|
||||
@@ -209,25 +208,6 @@ class InlineNode::Lambda final : public nf7::Node::Lambda,
|
||||
// used on luajit thread
|
||||
std::optional<nf7::luajit::Ref> func_;
|
||||
std::optional<nf7::luajit::Ref> ctxtable_;
|
||||
|
||||
|
||||
void HandleThread(const std::shared_ptr<nf7::luajit::Queue>& ljq,
|
||||
nf7::luajit::Thread& th, lua_State* L) noexcept {
|
||||
switch (th.state()) {
|
||||
case nf7::luajit::Thread::kFinished:
|
||||
return;
|
||||
|
||||
case nf7::luajit::Thread::kPaused:
|
||||
log_->Warn("unexpected yield");
|
||||
ljq->Push(shared_from_this(),
|
||||
[th = th.shared_from_this(), L](auto) { th->Resume(L, 0); });
|
||||
return;
|
||||
|
||||
default:
|
||||
log_->Warn("luajit execution error: "s+lua_tostring(L, -1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@@ -204,7 +204,8 @@ class Node::Lambda final : public nf7::Node::Lambda,
|
||||
|
||||
auto ljq = func->ljq();
|
||||
auto th = std::make_shared<nf7::luajit::Thread>(
|
||||
self, ljq, [self, ljq](auto& th, auto L) { self->HandleThread(ljq, th, L); });
|
||||
self, ljq,
|
||||
nf7::luajit::Thread::CreateNodeLambdaHandler(caller, shared_from_this()));
|
||||
th->Install(log_);
|
||||
th_.emplace_back(th);
|
||||
|
||||
@@ -215,7 +216,6 @@ class Node::Lambda final : public nf7::Node::Lambda,
|
||||
// push args
|
||||
lua_pushstring(thL, k.c_str());
|
||||
nf7::luajit::PushValue(thL, v);
|
||||
nf7::luajit::PushNodeLambda(thL, caller, self);
|
||||
|
||||
// push context table
|
||||
if (ctxtable_ && ctxtable_->ljq() != ljq) {
|
||||
@@ -230,26 +230,9 @@ class Node::Lambda final : public nf7::Node::Lambda,
|
||||
}
|
||||
|
||||
// execute
|
||||
th->Resume(thL, 4);
|
||||
th->Resume(thL, 3);
|
||||
});
|
||||
}
|
||||
void HandleThread(const std::shared_ptr<nf7::luajit::Queue>& ljq,
|
||||
nf7::luajit::Thread& th, lua_State* L) noexcept {
|
||||
switch (th.state()) {
|
||||
case nf7::luajit::Thread::kFinished:
|
||||
return;
|
||||
|
||||
case nf7::luajit::Thread::kPaused:
|
||||
log_->Warn("unexpected yield");
|
||||
ljq->Push(shared_from_this(),
|
||||
[th = th.shared_from_this(), L](auto) { th->Resume(L, 0); });
|
||||
return;
|
||||
|
||||
default:
|
||||
log_->Warn("luajit execution error: "s+lua_tostring(L, -1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user