111 lines
2.8 KiB
C++
111 lines
2.8 KiB
C++
// No copyright
|
|
#include "core/luajit/context.hh"
|
|
|
|
#include "iface/subsys/concurrency.hh"
|
|
#include "iface/subsys/parallelism.hh"
|
|
|
|
|
|
namespace nf7::core::luajit {
|
|
|
|
Value::~Value() noexcept {
|
|
ctx_->Push(Task {[index = index_](auto& ctx) {
|
|
luaL_unref(*ctx, LUA_REGISTRYINDEX, index);
|
|
}});
|
|
}
|
|
|
|
|
|
std::shared_ptr<Value> TaskContext::Register() noexcept {
|
|
const auto index = luaL_ref(state_, LUA_REGISTRYINDEX);
|
|
return std::make_shared<Value>(ctx_, index);
|
|
}
|
|
|
|
void TaskContext::Query(const Value& value) noexcept {
|
|
assert(value.context() == ctx_);
|
|
lua_rawgeti(state_, LUA_REGISTRYINDEX, value.index());
|
|
}
|
|
|
|
void TaskContext::Push(const nf7::Value& v) noexcept {
|
|
NewUserData(v);
|
|
if (luaL_newmetatable(state_, "nf7::Value")) {
|
|
lua_createtable(state_, 0, 0);
|
|
{
|
|
lua_pushcfunction(state_, [](auto L) {
|
|
const nf7::Value& v = CheckUserData<nf7::Value>(L, 1, "nf7::Value");
|
|
lua_pushstring(L,
|
|
v.is<nf7::Value::Null>() ? "null":
|
|
v.is<nf7::Value::Integer>()? "integer":
|
|
v.is<nf7::Value::Real>() ? "real":
|
|
v.is<nf7::Value::Buffer>() ? "buffer":
|
|
v.is<nf7::Value::Object>() ? "object":
|
|
"unknown");
|
|
return 1;
|
|
});
|
|
lua_setfield(state_, -2, "type");
|
|
|
|
// TODO(falsycat)
|
|
}
|
|
lua_setfield(state_, -2, "__index");
|
|
}
|
|
lua_setmetatable(state_, -2);
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
class ContextImpl final : public Context {
|
|
public:
|
|
ContextImpl(const char* name, Kind kind, Env& env)
|
|
: Context(name, kind), tasq_(env.Get<T>()) {
|
|
auto L = state();
|
|
|
|
lua_pushthread(L);
|
|
if (luaL_newmetatable(L, "nf7::Context::ImmutableEnv")) {
|
|
lua_createtable(L, 0, 0);
|
|
{
|
|
luaL_newmetatable(L, kGlobalTableName);
|
|
lua_setfield(L, -2, "__index");
|
|
|
|
lua_pushcfunction(L, [](auto L) {
|
|
return luaL_error(L, "global is immutable");
|
|
});
|
|
lua_setfield(L, -2, "__newindex");
|
|
}
|
|
lua_setmetatable(L, -2);
|
|
}
|
|
lua_setfenv(L, -2);
|
|
lua_pop(L, 1);
|
|
}
|
|
|
|
void Push(Task&& task) noexcept override {
|
|
auto self = std::dynamic_pointer_cast<ContextImpl<T>>(shared_from_this());
|
|
tasq_->Push(typename T::Item {
|
|
[self, task = std::move(task)](auto&) mutable {
|
|
TaskContext ctx {self, self->state()};
|
|
lua_settop(*ctx, 0);
|
|
task(ctx);
|
|
},
|
|
task.location()
|
|
});
|
|
}
|
|
|
|
protected:
|
|
using Context::shared_from_this;
|
|
|
|
private:
|
|
std::shared_ptr<T> tasq_;
|
|
};
|
|
|
|
std::shared_ptr<Context> Context::Create(Env& env, Kind kind) {
|
|
switch (kind) {
|
|
case kSync:
|
|
return std::make_shared<ContextImpl<subsys::Concurrency>>(
|
|
"nf7::core::luajit::SyncContext", kSync, env);
|
|
case kAsync:
|
|
return std::make_shared<ContextImpl<subsys::Parallelism>>(
|
|
"nf7::core::luajit::AsyncContext", kAsync, env);
|
|
default:
|
|
assert(false);
|
|
}
|
|
}
|
|
|
|
} // namespace nf7::core::luajit
|