add nf7::GenericWatcher

This commit is contained in:
falsycat 2022-06-10 18:23:03 +09:00
parent 744863f466
commit d192d6cf91
3 changed files with 63 additions and 44 deletions

View File

@ -56,6 +56,7 @@ target_sources(nf7
common/generic_history.hh
common/generic_memento.hh
common/generic_type_info.hh
common/generic_watcher.hh
common/gui_file.hh
common/gui_node.hh
common/gui_window.hh

30
common/generic_watcher.hh Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <unordered_map>
#include "nf7.hh"
namespace nf7 {
class GenericWatcher final : public Env::Watcher {
public:
using Handler = std::function<void(const File::Event&)>;
GenericWatcher(Env& env) noexcept : Watcher(env) {
}
void AddHandler(File::Event::Type type, Handler&& h) noexcept {
handlers_[type] = std::move(h);
}
void Handle(const File::Event& ev) noexcept override {
auto handler = handlers_.find(ev.type);
if (handler == handlers_.end()) return;
handler->second(ev);
}
private:
std::unordered_map<File::Event::Type, Handler> handlers_;
};
} // namespace nf7

View File

@ -17,6 +17,7 @@
#include "common/future.hh"
#include "common/generic_context.hh"
#include "common/generic_type_info.hh"
#include "common/generic_watcher.hh"
#include "common/lock.hh"
#include "common/luajit.hh"
#include "common/luajit_obj.hh"
@ -42,7 +43,6 @@ class Obj final : public nf7::File,
static constexpr size_t kMaxSize = 1024*1024*16; /* = 16 MiB */
class SrcWatcher;
class ExecTask;
Obj(Env& env, Path&& path = {}) noexcept :
@ -75,8 +75,8 @@ class Obj final : public nf7::File,
private:
std::shared_ptr<nf7::LoggerRef> log_;
std::unique_ptr<SrcWatcher> srcwatcher_;
std::shared_ptr<nf7::luajit::Ref> cache_;
std::optional<nf7::GenericWatcher> watcher_;
std::shared_ptr<nf7::luajit::Ref> cache_;
nf7::Task<std::shared_ptr<nf7::luajit::Ref>>::Holder exec_;
@ -94,27 +94,6 @@ class Obj final : public nf7::File,
void Reset() noexcept;
};
class Obj::SrcWatcher final : public nf7::Env::Watcher {
public:
SrcWatcher(Obj& owner, File::Id id) :
Watcher(owner.env()), owner_(&owner) {
if (owner.id() == id) throw Exception("self watch");
if (id == 0) throw Exception("invalid id");
Watch(id);
}
void Handle(const File::Event& ev) noexcept override {
if (ev.type == File::Event::kUpdate) {
owner_->log_->Info("detected update of source file, drops cache automatically");
owner_->cache_ = nullptr;
owner_->Touch();
}
}
private:
Obj* const owner_;
};
class Obj::ExecTask final : public nf7::Task<std::shared_ptr<nf7::luajit::Ref>> {
public:
ExecTask(Obj& target) noexcept :
@ -175,9 +154,28 @@ class Obj::ExecTask final : public nf7::Task<std::shared_ptr<nf7::luajit::Ref>>
return luaL_ref(L, LUA_REGISTRYINDEX);
});
// context for luajit script running
auto lua_ctx = std::make_shared<nf7::GenericContext>(env(), initiator());
lua_ctx->description() = "luajit object build script runner";
// setup watcher
try {
*target_->src_; // check if the src is alive
auto& w = target_->watcher_;
w.emplace(env());
w->Watch(srcf.id());
std::weak_ptr<Task> wself = self();
w->AddHandler(Event::kUpdate, [t = target_, wself](auto&) {
if (auto self = wself.lock()) {
t->log_->Info("detected update of source file, aborts building");
t->exec_ = {};
} else if (t->cache_) {
t->log_->Info("detected update of source file, drops cache automatically");
t->cache_ = nullptr;
t->Touch();
}
});
} catch (Exception& e) {
log_->Warn("watcher setup error: "+e.msg());
}
// queue task to trigger the thread
auto ljq = target_->
@ -242,18 +240,12 @@ nf7::Future<std::shared_ptr<nf7::luajit::Ref>> Obj::Build() noexcept {
void Obj::Handle(const Event& ev) noexcept {
switch (ev.type) {
case Event::kAdd:
try {
log_->SetUp(*this);
auto ctx = std::make_shared<nf7::GenericContext>(env(), id());
ctx->description() = "resetting state";
env().ExecMain(ctx, [this]() { Reset(); });
} catch (Exception&) {
}
log_->SetUp(*this);
break;
case Event::kRemove:
exec_ = {};
cache_ = nullptr;
srcwatcher_ = nullptr;
exec_ = {};
cache_ = nullptr;
watcher_ = std::nullopt;
log_->TearDown();
break;
@ -262,13 +254,9 @@ void Obj::Handle(const Event& ev) noexcept {
}
}
void Obj::Reset() noexcept {
exec_ = {};
cache_ = nullptr;
try {
srcwatcher_ = std::make_unique<SrcWatcher>(*this, src_.id());
} catch (Exception&) {
srcwatcher_ = nullptr;
}
exec_ = {};
cache_ = nullptr;
watcher_ = std::nullopt;
}
void Obj::Update() noexcept {