diff --git a/main.cc b/main.cc index 772a2de..1a487ea 100644 --- a/main.cc +++ b/main.cc @@ -214,14 +214,16 @@ class Env final : public nf7::Env { f.Handle(e); // trigger file watcher - auto itr = watchers_map_.find(e.id); - if (itr != watchers_map_.end()) { + auto itr = watchers_.find(e.id); + if (itr != watchers_.end()) { for (auto w : itr->second) w->Handle(e); } // trigger global watcher - for (auto w : watchers_map_[0]) w->Handle(e); - + itr = watchers_.find(0); + if (itr != watchers_.end()) { + for (auto w : itr->second) w->Handle(e); + } return &f; } catch (nf7::ExpiredException&) { return nullptr; @@ -269,15 +271,17 @@ class Env final : public nf7::Env { } void AddWatcher(nf7::File::Id id, nf7::Env::Watcher& w) noexcept override { - watchers_map_[id].push_back(&w); - watchers_rmap_[&w].push_back(id); + watchers_[id].push_back(&w); } - void RemoveWatcher(nf7::Env::Watcher& w) noexcept override { - for (const auto id : watchers_rmap_[&w]) { - auto& v = watchers_map_[id]; + void RemoveWatcher(nf7::File::Id id, nf7::Env::Watcher& w) noexcept override { + auto itr = watchers_.find(id); + if (watchers_.end() != itr) { + auto& v = itr->second; v.erase(std::remove(v.begin(), v.end(), &w), v.end()); + if (v.size() == 0) { + watchers_.erase(itr); + } } - watchers_rmap_.erase(&w); } private: @@ -288,8 +292,7 @@ class Env final : public nf7::Env { nf7::File::Id file_next_ = 1; std::unordered_map files_; - std::unordered_map> watchers_map_; - std::unordered_map> watchers_rmap_; + std::unordered_map> watchers_; }; diff --git a/nf7.cc b/nf7.cc index f046c62..6251da7 100644 --- a/nf7.cc +++ b/nf7.cc @@ -265,10 +265,22 @@ File& Env::GetFileOrThrow(File::Id id) const { Env::Watcher::Watcher(Env& env) noexcept : env_(&env) { } Env::Watcher::~Watcher() noexcept { - env_->RemoveWatcher(*this); + for (auto id : targets_) { + env_->RemoveWatcher(id, *this); + } } void Env::Watcher::Watch(File::Id id) noexcept { - env_->AddWatcher(id, *this); + if (targets_.end() == std::find(targets_.begin(), targets_.end(), id)) { + targets_.push_back(id); + env_->AddWatcher(id, *this); + } +} +void Env::Watcher::Unwatch(File::Id id) noexcept { + auto itr = std::remove(targets_.begin(), targets_.end(), id); + if (itr != targets_.end()) { + targets_.erase(itr); + env_->RemoveWatcher(id, *this); + } } diff --git a/nf7.hh b/nf7.hh index be4f52f..e608117 100644 --- a/nf7.hh +++ b/nf7.hh @@ -302,7 +302,7 @@ class Env { virtual void RemoveFile(File::Id) noexcept = 0; virtual void AddWatcher(File::Id, Watcher&) noexcept = 0; - virtual void RemoveWatcher(Watcher&) noexcept = 0; + virtual void RemoveWatcher(File::Id, Watcher&) noexcept = 0; private: std::filesystem::path npath_; @@ -316,12 +316,17 @@ class Env::Watcher { Watcher& operator=(const Watcher&) = delete; Watcher& operator=(Watcher&&) = delete; + void Watch(File::Id) noexcept; + void Unwatch(File::Id) noexcept; + virtual void Handle(const File::Event&) noexcept = 0; - void Watch(File::Id) noexcept; + const std::vector& targets() const noexcept { return targets_; } private: Env* const env_; + + std::vector targets_; };