diff --git a/include/modules/meta/base.hpp b/include/modules/meta/base.hpp index 23e74fbf..aed26f6f 100644 --- a/include/modules/meta/base.hpp +++ b/include/modules/meta/base.hpp @@ -37,7 +37,7 @@ namespace drawtypes { using animation_t = shared_ptr; class iconset; using iconset_t = shared_ptr; -} +} // namespace drawtypes class builder; class config; @@ -130,6 +130,8 @@ namespace modules { void broadcast(); void idle(); void sleep(chrono::duration duration); + template + void sleep_until(chrono::time_point point); void wakeup(); string get_format() const; string get_output(); @@ -160,6 +162,6 @@ namespace modules { }; // }}} -} +} // namespace modules POLYBAR_NS_END diff --git a/include/modules/meta/base.inl b/include/modules/meta/base.inl index d7e96312..73255347 100644 --- a/include/modules/meta/base.inl +++ b/include/modules/meta/base.inl @@ -116,6 +116,15 @@ namespace modules { } } + template + template + void module::sleep_until(chrono::time_point point) { + if (running()) { + std::unique_lock lck(m_sleeplock); + m_sleephandler.wait_until(lck, point); + } + } + template void module::wakeup() { m_log.trace("%s: Release sleep lock", name()); diff --git a/include/modules/meta/timer_module.hpp b/include/modules/meta/timer_module.hpp index aa1ed96b..d4f1a4a2 100644 --- a/include/modules/meta/timer_module.hpp +++ b/include/modules/meta/timer_module.hpp @@ -34,7 +34,21 @@ namespace modules { if (check()) { CAST_MOD(Impl)->broadcast(); } - CAST_MOD(Impl)->sleep(m_interval); + // wait until next full interval to avoid drifting clocks + using clock = chrono::system_clock; + using sys_duration_t = clock::time_point::duration; + + auto sys_interval = chrono::duration_cast(m_interval); + clock::time_point now = clock::now(); + sys_duration_t adjusted = sys_interval - (now.time_since_epoch() % sys_interval); + + // The seemingly arbitrary addition of 500ms is due + // to the fact that if we wait the exact time our + // thread will be woken just a tiny bit prematurely + // and therefore the wrong time will be displayed. + // It is currently unknown why exactly the thread gets + // woken prematurely. + CAST_MOD(Impl)->sleep_until(now + adjusted + 500ms); } } catch (const exception& err) { CAST_MOD(Impl)->halt(err.what()); @@ -44,6 +58,6 @@ namespace modules { protected: interval_t m_interval{1.0}; }; -} +} // namespace modules POLYBAR_NS_END