implement querying an external Lua object from LuaJIT/Obj file
rename nf7:lock() -> nf7:query()
This commit is contained in:
parent
f86c7c6b2e
commit
2152203bd7
@ -4,6 +4,7 @@
|
||||
#include <tuple>
|
||||
|
||||
#include "common/async_buffer.hh"
|
||||
#include "common/luajit_obj.hh"
|
||||
|
||||
|
||||
namespace nf7::luajit {
|
||||
@ -13,12 +14,270 @@ constexpr size_t kInstructionLimit = 10000000;
|
||||
constexpr size_t kBufferSizeMax = 64 * 1024 * 1024;
|
||||
|
||||
|
||||
// Pushes a metatable for Thread object, available on global table as 'nf7'.
|
||||
static void PushMeta(lua_State*) noexcept;
|
||||
|
||||
// Pushes Lua object built by a file who implements luajit::Obj interface.
|
||||
static void GetLuaObjAndPush(
|
||||
lua_State* L, const std::shared_ptr<Thread>& th, File& f);
|
||||
|
||||
// Acquires a lock and push it to Lua stack using PushLock.
|
||||
template <typename T>
|
||||
static void AcquireAndPushLock(
|
||||
lua_State* L, const std::shared_ptr<Thread>& th, File& f, bool ex);
|
||||
|
||||
// Pushes an object associated to the lock.
|
||||
// Specialize this to implement custom method depended a type of locked resource.
|
||||
template <typename T>
|
||||
static void PushLock(
|
||||
lua_State* L,
|
||||
const std::shared_ptr<Thread>&,
|
||||
const std::shared_ptr<T>&,
|
||||
const std::shared_ptr<nf7::Lock>&) noexcept;
|
||||
|
||||
|
||||
Thread::~Thread() noexcept {
|
||||
if (holder_) *holder_ = nullptr;
|
||||
}
|
||||
void Thread::Resume(lua_State* L, int narg) noexcept {
|
||||
std::unique_lock<std::mutex> k(mtx_);
|
||||
|
||||
if (state_ == kAborted) return;
|
||||
assert(holder_);
|
||||
assert(L == th_);
|
||||
assert(state_ == kPaused);
|
||||
(void) L;
|
||||
|
||||
static const auto kHook = [](auto L, auto) {
|
||||
luaL_error(L, "reached instruction limit (<=1e7)");
|
||||
};
|
||||
lua_sethook(th_, kHook, LUA_MASKCOUNT, kInstructionLimit);
|
||||
|
||||
PushGlobalTable(th_);
|
||||
PushWeakPtr(th_, weak_from_this());
|
||||
PushMeta(th_);
|
||||
lua_setmetatable(th_, -2);
|
||||
lua_setfield(th_, -2, "nf7");
|
||||
lua_pop(th_, 1);
|
||||
|
||||
state_ = kRunning;
|
||||
k.unlock();
|
||||
const auto ret = lua_resume(th_, narg);
|
||||
k.lock();
|
||||
if (state_ == kAborted) return;
|
||||
switch (ret) {
|
||||
case 0:
|
||||
state_ = kFinished;
|
||||
if (holder_) *holder_ = nullptr;
|
||||
break;
|
||||
case LUA_YIELD:
|
||||
state_ = kPaused;
|
||||
break;
|
||||
default:
|
||||
state_ = kAborted;
|
||||
if (holder_) *holder_ = nullptr;
|
||||
}
|
||||
if (!std::exchange(skip_handle_, false)) {
|
||||
handler_(*this, th_);
|
||||
}
|
||||
}
|
||||
void Thread::Abort() noexcept {
|
||||
std::unique_lock<std::mutex> k(mtx_);
|
||||
state_ = kAborted;
|
||||
if (holder_) *holder_ = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void Thread::Holder::Handle(const nf7::File::Event& ev) noexcept {
|
||||
std::unique_lock<std::mutex> k(mtx_);
|
||||
|
||||
switch (ev.type) {
|
||||
case nf7::File::Event::kAdd:
|
||||
assert(isolated_);
|
||||
isolated_ = false;
|
||||
|
||||
if (th_) {
|
||||
th_->file_parent_ = owner_;
|
||||
if (auto& f = th_->file_) {
|
||||
assert(!f->parent());
|
||||
f->MoveUnder(*owner_, "file");
|
||||
}
|
||||
}
|
||||
return;
|
||||
case nf7::File::Event::kRemove:
|
||||
assert(!isolated_);
|
||||
isolated_ = true;
|
||||
|
||||
if (th_) {
|
||||
th_->file_parent_ = nullptr;
|
||||
if (auto& f = th_->file_) {
|
||||
assert(f->parent());
|
||||
f->Isolate();
|
||||
}
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
void Thread::Holder::Assign(const std::shared_ptr<Thread>& th) noexcept {
|
||||
if (th_ == th) return;
|
||||
if (th_) {
|
||||
th_->holder_ = nullptr;
|
||||
if (!isolated_) {
|
||||
if (auto& f = th_->file_) {
|
||||
assert(f->parent());
|
||||
f->Isolate();
|
||||
}
|
||||
}
|
||||
}
|
||||
th_ = th;
|
||||
if (th_) {
|
||||
th_->holder_ = this;
|
||||
if (!isolated_) {
|
||||
if (auto& f = th_->file_) {
|
||||
assert(!f->parent());
|
||||
f->MoveUnder(*owner_, "file");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void PushMeta(lua_State* L) noexcept {
|
||||
if (luaL_newmetatable(L, kTypeName)) {
|
||||
PushWeakPtrDeleter<Thread>(L);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
|
||||
lua_createtable(L, 0, 0);
|
||||
{
|
||||
// nf7:resolve(path)
|
||||
lua_pushcfunction(L, [](auto L) {
|
||||
auto th = CheckWeakPtr<Thread>(L, 1, kTypeName);
|
||||
auto base = th->ctx()->initiator();
|
||||
|
||||
std::string path = luaL_checkstring(L, 2);
|
||||
th->env().ExecSub(th->ctx(), [th, L, base, path = std::move(path)]() {
|
||||
nf7::File::Id ret;
|
||||
try {
|
||||
ret = th->env().GetFileOrThrow(base).ResolveOrThrow(path).id();
|
||||
} catch (nf7::File::NotFoundException&) {
|
||||
ret = 0;
|
||||
}
|
||||
th->ljq()->Push(th->ctx(), [th, L, ret](auto) {
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(ret));
|
||||
th->Resume(L, 1);
|
||||
});
|
||||
});
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, 0);
|
||||
});
|
||||
lua_setfield(L, -2, "resolve");
|
||||
|
||||
// nf7:query(file_id, interface)
|
||||
lua_pushcfunction(L, [](auto L) {
|
||||
auto th = CheckWeakPtr<Thread>(L, 1, kTypeName);
|
||||
|
||||
const auto id = luaL_checkinteger(L, 2);
|
||||
std::string iface = luaL_checkstring(L, 3);
|
||||
const auto ex = lua_toboolean(L, 4);
|
||||
th->env().ExecMain(th->ctx(), [th, L, id, iface = std::move(iface), ex]() {
|
||||
try {
|
||||
auto& f = th->env().GetFileOrThrow(static_cast<nf7::File::Id>(id));
|
||||
if (iface == "buffer") {
|
||||
AcquireAndPushLock<nf7::AsyncBuffer>(L, th, f, ex);
|
||||
} else if (iface == "lua") {
|
||||
GetLuaObjAndPush(L, th, f);
|
||||
} else {
|
||||
throw nf7::Exception {"unknown interface: "+iface};
|
||||
}
|
||||
} catch (nf7::Exception&) {
|
||||
th->ljq()->Push(th->ctx(), [th, L](auto) { th->Resume(L, 0); });
|
||||
}
|
||||
});
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, 0);
|
||||
});
|
||||
lua_setfield(L, -2, "query");
|
||||
|
||||
// nf7:yield(results...)
|
||||
lua_pushcfunction(L, [](auto L) {
|
||||
auto th = CheckWeakPtr<Thread>(L, 1, kTypeName);
|
||||
th->ExecResume(L);
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, lua_gettop(L)-1);
|
||||
});
|
||||
lua_setfield(L, -2, "yield");
|
||||
|
||||
// logging functions
|
||||
static const auto log_write = [](lua_State* L, nf7::Logger::Level lv) {
|
||||
auto th = CheckWeakPtr<Thread>(L, 1, kTypeName);
|
||||
auto logger = th->logger();
|
||||
if (!logger) return luaL_error(L, "logger is not installed on current thread");
|
||||
|
||||
const int n = lua_gettop(L);
|
||||
std::stringstream st;
|
||||
for (int i = 2; i <= n; ++i) {
|
||||
st << lua_tostring(L, i);
|
||||
}
|
||||
logger->Write({lv, st.str()});
|
||||
return 0;
|
||||
};
|
||||
lua_pushcfunction(L, [](auto L) { return log_write(L, nf7::Logger::kTrace); });
|
||||
lua_setfield(L, -2, "trace");
|
||||
lua_pushcfunction(L, [](auto L) { return log_write(L, nf7::Logger::kInfo); });
|
||||
lua_setfield(L, -2, "info");
|
||||
lua_pushcfunction(L, [](auto L) { return log_write(L, nf7::Logger::kWarn); });
|
||||
lua_setfield(L, -2, "warn");
|
||||
lua_pushcfunction(L, [](auto L) { return log_write(L, nf7::Logger::kError); });
|
||||
lua_setfield(L, -2, "error");
|
||||
}
|
||||
lua_setfield(L, -2, "__index");
|
||||
}
|
||||
}
|
||||
|
||||
static void GetLuaObjAndPush(
|
||||
lua_State* L, const std::shared_ptr<Thread>& th, File& f) {
|
||||
f.interfaceOrThrow<nf7::luajit::Obj>().Build().
|
||||
Then([th, L](auto fu) {
|
||||
th->ljq()->Push(th->ctx(), [th, L, fu](auto) mutable {
|
||||
try {
|
||||
const auto& obj = fu.value();
|
||||
if (th->ljq() != obj->ljq()) {
|
||||
throw nf7::Exception {"the object is built on other LuaJIT context"};
|
||||
}
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, obj->index());
|
||||
th->Resume(L, 1);
|
||||
} catch (nf7::Exception& e) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, e.msg().c_str());
|
||||
th->Resume(L, 2);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void AcquireAndPushLock(
|
||||
lua_State* L, const std::shared_ptr<Thread>& th, File& f, bool ex) {
|
||||
auto& res = f.interfaceOrThrow<T>();
|
||||
res.AcquireLock(ex).
|
||||
Then([th, L, res = res.self()](auto fu) {
|
||||
th->ljq()->Push(th->ctx(), [th, L, res, fu](auto) mutable {
|
||||
try {
|
||||
const auto& k = fu.value();
|
||||
th->RegisterLock(k);
|
||||
PushLock<T>(L, th, res, k);
|
||||
th->Resume(L, 1);
|
||||
} catch (nf7::Exception& e) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, e.msg().c_str());
|
||||
th->Resume(L, 2);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
void PushLock<nf7::AsyncBuffer>(
|
||||
lua_State* L,
|
||||
@ -91,19 +350,17 @@ void PushLock<nf7::AsyncBuffer>(
|
||||
|
||||
buf->Read(static_cast<size_t>(off), vec->data(), static_cast<size_t>(size)).
|
||||
Then([th, L, vec](auto fu) {
|
||||
try {
|
||||
vec->resize(fu.value());
|
||||
th->ljq()->Push(th->ctx(), [th, L, vec](auto) {
|
||||
th->ljq()->Push(th->ctx(), [th, L, vec, fu](auto) mutable {
|
||||
try {
|
||||
vec->resize(fu.value());
|
||||
luajit::PushMutableVector(L, std::move(*vec));
|
||||
th->Resume(L, 1);
|
||||
});
|
||||
} catch (nf7::Exception& e) {
|
||||
th->ljq()->Push(th->ctx(), [th, L, msg = e.msg()](auto) {
|
||||
} catch (nf7::Exception& e) {
|
||||
luajit::PushMutableVector(L, {});
|
||||
lua_pushstring(L, msg.c_str());
|
||||
lua_pushstring(L, e.msg().c_str());
|
||||
th->Resume(L, 2);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, 0);
|
||||
@ -127,19 +384,16 @@ void PushLock<nf7::AsyncBuffer>(
|
||||
|
||||
buf->Write(static_cast<size_t>(off), vec->data(), vec->size()).
|
||||
Then([th, L, vec](auto fu) {
|
||||
try {
|
||||
const auto ret = fu.value();
|
||||
th->ljq()->Push(th->ctx(), [th, L, ret](auto) {
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(ret));
|
||||
th->ljq()->Push(th->ctx(), [th, L, fu](auto) mutable {
|
||||
try {
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(fu.value()));
|
||||
th->Resume(L, 1);
|
||||
});
|
||||
} catch (nf7::Exception& e) {
|
||||
th->ljq()->Push(th->ctx(), [th, L, msg = e.msg()](auto) {
|
||||
} catch (nf7::Exception& e) {
|
||||
lua_pushinteger(L, 0);
|
||||
lua_pushstring(L, msg.c_str());
|
||||
lua_pushstring(L, e.msg().c_str());
|
||||
th->Resume(L, 2);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, 0);
|
||||
@ -157,19 +411,16 @@ void PushLock<nf7::AsyncBuffer>(
|
||||
|
||||
buf->Truncate(static_cast<size_t>(size)).
|
||||
Then([th, L](auto fu) {
|
||||
try {
|
||||
const auto ret = fu.value();
|
||||
th->ljq()->Push(th->ctx(), [th, L, ret](auto) {
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(ret));
|
||||
th->ljq()->Push(th->ctx(), [th, L, fu](auto) mutable {
|
||||
try {
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(fu.value()));
|
||||
th->Resume(L, 1);
|
||||
});
|
||||
} catch (nf7::Exception& e) {
|
||||
th->ljq()->Push(th->ctx(), [th, L, msg = e.msg()](auto) {
|
||||
lua_pushinteger(L, 0);
|
||||
lua_pushstring(L, msg.c_str());
|
||||
} catch (nf7::Exception& e) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, e.msg().c_str());
|
||||
th->Resume(L, 2);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, 0);
|
||||
@ -195,226 +446,4 @@ void PushLock<nf7::AsyncBuffer>(
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void AcquireAndPush(lua_State* L, const std::shared_ptr<Thread>& th, File& f, bool ex) {
|
||||
auto& obj = f.interfaceOrThrow<T>();
|
||||
obj.AcquireLock(ex).
|
||||
Then([th, L, obj = obj.self()](auto fu) {
|
||||
try {
|
||||
auto k = fu.value();
|
||||
th->ljq()->Push(th->ctx(), [th, L, obj, k](auto) {
|
||||
th->RegisterLock(k);
|
||||
PushLock<T>(L, th, obj, k);
|
||||
th->Resume(L, 1);
|
||||
});
|
||||
} catch (nf7::Exception& e) {
|
||||
th->ljq()->Push(th->ctx(), [th, L, msg = e.msg()](auto) {
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L, msg.c_str());
|
||||
th->Resume(L, 2);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Thread::~Thread() noexcept {
|
||||
if (holder_) *holder_ = nullptr;
|
||||
}
|
||||
|
||||
void Thread::PushMeta(lua_State* L) noexcept {
|
||||
if (luaL_newmetatable(L, kTypeName)) {
|
||||
PushWeakPtrDeleter<Thread>(L);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
|
||||
lua_createtable(L, 0, 0);
|
||||
{
|
||||
// nf7:resolve(path)
|
||||
lua_pushcfunction(L, [](auto L) {
|
||||
auto th = CheckWeakPtr<Thread>(L, 1, kTypeName);
|
||||
auto base = th->ctx_->initiator();
|
||||
|
||||
std::string path = luaL_checkstring(L, 2);
|
||||
th->env_.ExecSub(th->ctx_, [th, L, base, path = std::move(path)]() {
|
||||
nf7::File::Id ret;
|
||||
try {
|
||||
ret = th->env_.GetFileOrThrow(base).ResolveOrThrow(path).id();
|
||||
} catch (nf7::File::NotFoundException&) {
|
||||
ret = 0;
|
||||
}
|
||||
th->ljq_->Push(th->ctx_, [th, L, ret](auto) {
|
||||
lua_pushinteger(L, static_cast<lua_Integer>(ret));
|
||||
th->Resume(L, 1);
|
||||
});
|
||||
});
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, 0);
|
||||
});
|
||||
lua_setfield(L, -2, "resolve");
|
||||
|
||||
// nf7:lock(file_id, interface)
|
||||
lua_pushcfunction(L, [](auto L) {
|
||||
auto th = CheckWeakPtr<Thread>(L, 1, kTypeName);
|
||||
|
||||
const auto id = luaL_checkinteger(L, 2);
|
||||
std::string iface = luaL_checkstring(L, 3);
|
||||
const auto ex = lua_toboolean(L, 4);
|
||||
th->env_.ExecMain(th->ctx_, [th, L, id, iface = std::move(iface), ex]() {
|
||||
try {
|
||||
auto& f = th->env_.GetFileOrThrow(static_cast<nf7::File::Id>(id));
|
||||
if (iface == "buffer") {
|
||||
AcquireAndPush<nf7::AsyncBuffer>(L, th, f, ex);
|
||||
} else {
|
||||
throw nf7::Exception {"unknown interface: "+iface};
|
||||
}
|
||||
} catch (nf7::Exception&) {
|
||||
th->ljq_->Push(th->ctx_, [th, L](auto) { th->Resume(L, 0); });
|
||||
}
|
||||
});
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, 0);
|
||||
});
|
||||
lua_setfield(L, -2, "lock");
|
||||
|
||||
// nf7:yield(results...)
|
||||
lua_pushcfunction(L, [](auto L) {
|
||||
auto th = CheckWeakPtr<Thread>(L, 1, kTypeName);
|
||||
th->ExecResume(L);
|
||||
th->ExpectYield(L);
|
||||
return lua_yield(L, lua_gettop(L)-1);
|
||||
});
|
||||
lua_setfield(L, -2, "yield");
|
||||
|
||||
// logging functions
|
||||
static const auto log_write = [](lua_State* L, nf7::Logger::Level lv) {
|
||||
auto th = CheckWeakPtr<Thread>(L, 1, kTypeName);
|
||||
auto logger = th->logger_;
|
||||
if (!logger) return luaL_error(L, "logger is not installed on current thread");
|
||||
|
||||
const int n = lua_gettop(L);
|
||||
std::stringstream st;
|
||||
for (int i = 2; i <= n; ++i) {
|
||||
st << lua_tostring(L, i);
|
||||
}
|
||||
logger->Write({lv, st.str()});
|
||||
return 0;
|
||||
};
|
||||
lua_pushcfunction(L, [](auto L) { return log_write(L, nf7::Logger::kTrace); });
|
||||
lua_setfield(L, -2, "trace");
|
||||
lua_pushcfunction(L, [](auto L) { return log_write(L, nf7::Logger::kInfo); });
|
||||
lua_setfield(L, -2, "info");
|
||||
lua_pushcfunction(L, [](auto L) { return log_write(L, nf7::Logger::kWarn); });
|
||||
lua_setfield(L, -2, "warn");
|
||||
lua_pushcfunction(L, [](auto L) { return log_write(L, nf7::Logger::kError); });
|
||||
lua_setfield(L, -2, "error");
|
||||
}
|
||||
lua_setfield(L, -2, "__index");
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::Resume(lua_State* L, int narg) noexcept {
|
||||
std::unique_lock<std::mutex> k(mtx_);
|
||||
|
||||
if (state_ == kAborted) return;
|
||||
assert(holder_);
|
||||
assert(L == th_);
|
||||
assert(state_ == kPaused);
|
||||
(void) L;
|
||||
|
||||
static const auto kHook = [](auto L, auto) {
|
||||
luaL_error(L, "reached instruction limit (<=1e7)");
|
||||
};
|
||||
lua_sethook(th_, kHook, LUA_MASKCOUNT, kInstructionLimit);
|
||||
|
||||
PushGlobalTable(th_);
|
||||
PushWeakPtr(th_, weak_from_this());
|
||||
Thread::PushMeta(th_);
|
||||
lua_setmetatable(th_, -2);
|
||||
lua_setfield(th_, -2, "nf7");
|
||||
lua_pop(th_, 1);
|
||||
|
||||
state_ = kRunning;
|
||||
k.unlock();
|
||||
const auto ret = lua_resume(th_, narg);
|
||||
k.lock();
|
||||
if (state_ == kAborted) return;
|
||||
switch (ret) {
|
||||
case 0:
|
||||
state_ = kFinished;
|
||||
if (holder_) *holder_ = nullptr;
|
||||
break;
|
||||
case LUA_YIELD:
|
||||
state_ = kPaused;
|
||||
break;
|
||||
default:
|
||||
state_ = kAborted;
|
||||
if (holder_) *holder_ = nullptr;
|
||||
}
|
||||
if (!std::exchange(skip_handle_, false)) {
|
||||
handler_(*this, th_);
|
||||
}
|
||||
}
|
||||
void Thread::Abort() noexcept {
|
||||
std::unique_lock<std::mutex> k(mtx_);
|
||||
state_ = kAborted;
|
||||
if (holder_) *holder_ = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void Thread::Holder::Handle(const nf7::File::Event& ev) noexcept {
|
||||
std::unique_lock<std::mutex> k(mtx_);
|
||||
|
||||
switch (ev.type) {
|
||||
case nf7::File::Event::kAdd:
|
||||
assert(isolated_);
|
||||
isolated_ = false;
|
||||
|
||||
if (th_) {
|
||||
th_->file_parent_ = owner_;
|
||||
if (auto& f = th_->file_) {
|
||||
assert(!f->parent());
|
||||
f->MoveUnder(*owner_, "file");
|
||||
}
|
||||
}
|
||||
return;
|
||||
case nf7::File::Event::kRemove:
|
||||
assert(!isolated_);
|
||||
isolated_ = true;
|
||||
|
||||
if (th_) {
|
||||
th_->file_parent_ = nullptr;
|
||||
if (auto& f = th_->file_) {
|
||||
assert(f->parent());
|
||||
f->Isolate();
|
||||
}
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::Holder::Assign(const std::shared_ptr<Thread>& th) noexcept {
|
||||
if (th_ == th) return;
|
||||
if (th_) {
|
||||
th_->holder_ = nullptr;
|
||||
if (!isolated_) {
|
||||
if (auto& f = th_->file_) {
|
||||
assert(f->parent());
|
||||
f->Isolate();
|
||||
}
|
||||
}
|
||||
}
|
||||
th_ = th;
|
||||
if (th_) {
|
||||
th_->holder_ = this;
|
||||
if (!isolated_) {
|
||||
if (auto& f = th_->file_) {
|
||||
assert(!f->parent());
|
||||
f->MoveUnder(*owner_, "file");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace nf7::luajit
|
||||
|
@ -39,8 +39,6 @@ class Thread final : public std::enable_shared_from_this<Thread> {
|
||||
template <typename T>
|
||||
static Handler CreatePromiseHandler(nf7::Future<T>::Promise& pro, std::function<T(lua_State*)>&&) noexcept;
|
||||
|
||||
static void PushMeta(lua_State*) noexcept;
|
||||
|
||||
Thread() = delete;
|
||||
Thread(const std::shared_ptr<nf7::Context>& ctx,
|
||||
const std::shared_ptr<nf7::luajit::Queue>& ljq,
|
||||
@ -105,6 +103,7 @@ class Thread final : public std::enable_shared_from_this<Thread> {
|
||||
nf7::Env& env() noexcept { return env_; }
|
||||
const std::shared_ptr<nf7::Context>& ctx() const noexcept { return ctx_; }
|
||||
const std::shared_ptr<nf7::luajit::Queue>& ljq() const noexcept { return ljq_; }
|
||||
const std::shared_ptr<nf7::LoggerRef>& logger() const noexcept { return logger_; }
|
||||
State state() const noexcept { return state_; }
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user