diff --git a/common/logger_ref.hh b/common/logger_ref.hh index 9df17fa..1774c0f 100644 --- a/common/logger_ref.hh +++ b/common/logger_ref.hh @@ -2,6 +2,7 @@ #include #include +#include #include #include "nf7.hh" @@ -35,17 +36,17 @@ class LoggerRef final { } // thread-safe - void Trace(std::string_view msg) noexcept { - Write({nf7::Logger::kTrace, msg}); + void Trace(std::string_view msg, std::source_location s = std::source_location::current()) noexcept { + Write({nf7::Logger::kTrace, msg, 0, s}); } - void Info(std::string_view msg) noexcept { - Write({nf7::Logger::kInfo, msg}); + void Info(std::string_view msg, std::source_location s = std::source_location::current()) noexcept { + Write({nf7::Logger::kInfo, msg, 0, s}); } - void Warn(std::string_view msg) noexcept { - Write({nf7::Logger::kWarn, msg}); + void Warn(std::string_view msg, std::source_location s = std::source_location::current()) noexcept { + Write({nf7::Logger::kWarn, msg, 0, s}); } - void Error(std::string_view msg) noexcept { - Write({nf7::Logger::kError, msg}); + void Error(std::string_view msg, std::source_location s = std::source_location::current()) noexcept { + Write({nf7::Logger::kError, msg, 0, s}); } void Write(nf7::Logger::Item&& item) noexcept { if (!id_ || !logger_) return; diff --git a/common/luajit.cc b/common/luajit.cc index c3af065..49ca8f3 100644 --- a/common/luajit.cc +++ b/common/luajit.cc @@ -4,6 +4,10 @@ #include +#include "common/logger.hh" +#include "common/logger_ref.hh" +#include "common/luajit_thread.hh" + namespace nf7::luajit { diff --git a/common/luajit.hh b/common/luajit.hh index ba91895..be596d1 100644 --- a/common/luajit.hh +++ b/common/luajit.hh @@ -28,22 +28,9 @@ inline void PushWeakPtr(lua_State* L, const std::weak_ptr& wptr) noexcept { new (lua_newuserdata(L, sizeof(wptr))) std::weak_ptr(wptr); } template -inline std::weak_ptr& ToWeakPtr(lua_State* L, int idx) { - std::weak_ptr* wptr = reinterpret_cast(lua_touserdata(L, idx)); - return *wptr; -} -template -inline std::shared_ptr ToSharedPtr(lua_State* L, int idx) { - if (auto ret = ToWeakPtr(L, idx).lock()) { - return ret; - } - luaL_error(L, "object expired: %s", typeid(T).name()); - return nullptr; -} -template -inline void PushWeakPtrDeleter(lua_State* L, const std::weak_ptr& = {}) { +inline void PushWeakPtrDeleter(lua_State* L, const std::weak_ptr& = {}) noexcept { lua_pushcfunction(L, [](auto L) { - ToWeakPtr(L, 1).~weak_ptr(); + reinterpret_cast*>(lua_touserdata(L, 1))->~weak_ptr(); return 0; }); } @@ -55,12 +42,21 @@ inline bool MatchMetaName(lua_State* L, int idx, const char* type) noexcept { lua_pop(L, 2); return ret; } - template inline T* ToRef(lua_State* L, int idx, const char* type) noexcept { return MatchMetaName(L, idx, type)? reinterpret_cast(lua_touserdata(L, idx)): nullptr; } +template +inline std::shared_ptr CheckWeakPtr(lua_State* L, int idx, const char* type) { + auto ptr = reinterpret_cast*>(luaL_checkudata(L, idx, type)); + if (auto ret = ptr->lock()) { + return ret; + } else { + luaL_error(L, "object expired: %s", typeid(T).name()); + return nullptr; + } +} template inline T& CheckRef(lua_State* L, int idx, const char* type) { return *reinterpret_cast(luaL_checkudata(L, idx, type)); diff --git a/common/luajit_thread.cc b/common/luajit_thread.cc index a4092b4..485b1b4 100644 --- a/common/luajit_thread.cc +++ b/common/luajit_thread.cc @@ -1,9 +1,12 @@ #include "common/luajit_thread.hh" +#include + namespace nf7::luajit { -constexpr size_t kInstructionLimit = 10000000; +constexpr const char* kTypeName = "nf7::luajit::Thread"; +constexpr size_t kInstructionLimit = 10000000; Thread::~Thread() noexcept { @@ -11,19 +14,41 @@ Thread::~Thread() noexcept { } void Thread::PushMeta(lua_State* L) noexcept { - if (luaL_newmetatable(L, "nf7::luajit::Thread")) { + if (luaL_newmetatable(L, kTypeName)) { PushWeakPtrDeleter(L); lua_setfield(L, -2, "__gc"); lua_createtable(L, 0, 0); { lua_pushcfunction(L, [](auto L) { - auto th = ToSharedPtr(L, 1); + auto th = CheckWeakPtr(L, 1, kTypeName); th->ExpectYield(); th->ExecResume(L); return lua_yield(L, lua_gettop(L)-1); }); lua_setfield(L, -2, "yield"); + + static const auto log_write = [](lua_State* L, nf7::Logger::Level lv) { + auto th = CheckWeakPtr(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"); } diff --git a/common/luajit_thread.hh b/common/luajit_thread.hh index 7e03a28..f43e0d0 100644 --- a/common/luajit_thread.hh +++ b/common/luajit_thread.hh @@ -13,6 +13,7 @@ #include "nf7.hh" #include "common/future.hh" +#include "common/logger_ref.hh" #include "common/luajit.hh" #include "common/luajit_ref.hh" #include "common/proxy_env.hh" @@ -51,6 +52,11 @@ class Thread final : public std::enable_shared_from_this { Thread& operator=(const Thread&) = delete; Thread& operator=(Thread&&) = delete; + void Install(const std::shared_ptr& logger) noexcept { + assert(state_ == kInitial); + logger_ = logger; + } + // must be called on luajit thread lua_State* Init(lua_State* L) noexcept { assert(state_ == kInitial); @@ -72,6 +78,12 @@ class Thread final : public std::enable_shared_from_this { ljq_->Push(ctx_, [this, L, self = shared_from_this()](auto) { Resume(L, 0); }); } + // must be called on luajit thread + // handler_ won't be called on next yielding + void ExpectYield() noexcept { + skip_handle_ = true; + } + // thread-safe void Abort() noexcept; @@ -82,12 +94,6 @@ class Thread final : public std::enable_shared_from_this { } } - // must be called on luajit thread - // handler_ won't be called on next yielding - void ExpectYield() noexcept { - skip_handle_ = true; - } - nf7::Env& env() noexcept { return env_; } const std::shared_ptr& ctx() const noexcept { return ctx_; } const std::shared_ptr& ljq() const noexcept { return ljq_; } @@ -109,6 +115,10 @@ class Thread final : public std::enable_shared_from_this { std::optional th_ref_; + // installed features + std::shared_ptr logger_; + + // mutable params Holder* holder_ = nullptr;