polybar/include/modules/meta/inotify_module.hpp

94 lines
2.4 KiB
C++

#pragma once
#include "components/builder.hpp"
#include "modules/meta/base.hpp"
POLYBAR_NS
namespace modules {
template <class Impl>
class inotify_module : public module<Impl> {
public:
using module<Impl>::module;
void start() {
this->m_mainthread = thread(&inotify_module::runner, this);
}
protected:
void runner() {
this->m_log.trace("%s: Thread id = %i", this->name(), concurrency_util::thread_id(this_thread::get_id()));
try {
// Warm up module output before entering the loop
std::unique_lock<std::mutex> guard(this->m_updatelock);
CAST_MOD(Impl)->on_event(nullptr);
CAST_MOD(Impl)->broadcast();
guard.unlock();
while (this->running()) {
std::lock_guard<std::mutex> guard(this->m_updatelock);
CAST_MOD(Impl)->poll_events();
}
} catch (const module_error& err) {
CAST_MOD(Impl)->halt(err.what());
} catch (const std::exception& err) {
CAST_MOD(Impl)->halt(err.what());
}
}
void watch(string path, int mask = IN_ALL_EVENTS) {
this->m_log.trace("%s: Attach inotify at %s", this->name(), path);
m_watchlist.insert(make_pair(path, mask));
}
void idle() {
this->sleep(200ms);
}
void poll_events() {
vector<unique_ptr<inotify_watch>> watches;
try {
for (auto&& w : m_watchlist) {
watches.emplace_back(inotify_util::make_watch(w.first));
watches.back()->attach(w.second);
}
} catch (const system_error& e) {
watches.clear();
this->m_log.err("%s: Error while creating inotify watch (what: %s)", this->name(), e.what());
CAST_MOD(Impl)->sleep(0.1s);
return;
}
while (this->running()) {
for (auto&& w : watches) {
this->m_log.trace_x("%s: Poll inotify watch %s", this->name(), w->path());
if (w->poll(1000 / watches.size())) {
auto event = w->get_event();
for (auto&& w : watches) {
w->remove(true);
}
if (CAST_MOD(Impl)->on_event(event.get())) {
CAST_MOD(Impl)->broadcast();
}
CAST_MOD(Impl)->idle();
return;
}
if (!this->running())
break;
}
CAST_MOD(Impl)->idle();
}
}
private:
map<string, int> m_watchlist;
};
}
POLYBAR_NS_END