fix(timer_module): sleep until next full interval (#2123)
Any timer_module based module would sleep for the set interval and then continue running. Depending on the start time of polybar this sleep pattern might not be aligned, which causes such modules to always update in a shifted manner. Consider the date module as an example. If the update interval is set to 60 seconds and polybar was started at 13:37:37, polybar would update the clock at 13:38:37, 13:39:37 and so on. To make matters worse, if a module would perform lengthy checks this interval might drift over time, causing even more inconsistent updating. This patch extends the base module with a sleep_until method that calls the corresponding function on the sleephandler. Additionally the timer_module is extended to compute the remaining time until the next interval passes and sleep accordingly. Closes #2064 Co-developed-by: Dominik Töllner <dominik.toellner@stud.uni-hannover.de> Co-authored-by: Malte Bargholz <malte@screenri.de>
This commit is contained in:
parent
2b6abb9b8f
commit
a625e2b79a
@ -37,7 +37,7 @@ namespace drawtypes {
|
|||||||
using animation_t = shared_ptr<animation>;
|
using animation_t = shared_ptr<animation>;
|
||||||
class iconset;
|
class iconset;
|
||||||
using iconset_t = shared_ptr<iconset>;
|
using iconset_t = shared_ptr<iconset>;
|
||||||
}
|
} // namespace drawtypes
|
||||||
|
|
||||||
class builder;
|
class builder;
|
||||||
class config;
|
class config;
|
||||||
@ -130,6 +130,8 @@ namespace modules {
|
|||||||
void broadcast();
|
void broadcast();
|
||||||
void idle();
|
void idle();
|
||||||
void sleep(chrono::duration<double> duration);
|
void sleep(chrono::duration<double> duration);
|
||||||
|
template <class Clock, class Duration>
|
||||||
|
void sleep_until(chrono::time_point<Clock, Duration> point);
|
||||||
void wakeup();
|
void wakeup();
|
||||||
string get_format() const;
|
string get_format() const;
|
||||||
string get_output();
|
string get_output();
|
||||||
@ -160,6 +162,6 @@ namespace modules {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
}
|
} // namespace modules
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -116,6 +116,15 @@ namespace modules {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Impl>
|
||||||
|
template <class Clock, class Duration>
|
||||||
|
void module<Impl>::sleep_until(chrono::time_point<Clock, Duration> point) {
|
||||||
|
if (running()) {
|
||||||
|
std::unique_lock<std::mutex> lck(m_sleeplock);
|
||||||
|
m_sleephandler.wait_until(lck, point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Impl>
|
template <typename Impl>
|
||||||
void module<Impl>::wakeup() {
|
void module<Impl>::wakeup() {
|
||||||
m_log.trace("%s: Release sleep lock", name());
|
m_log.trace("%s: Release sleep lock", name());
|
||||||
|
@ -34,7 +34,21 @@ namespace modules {
|
|||||||
if (check()) {
|
if (check()) {
|
||||||
CAST_MOD(Impl)->broadcast();
|
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<sys_duration_t>(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) {
|
} catch (const exception& err) {
|
||||||
CAST_MOD(Impl)->halt(err.what());
|
CAST_MOD(Impl)->halt(err.what());
|
||||||
@ -44,6 +58,6 @@ namespace modules {
|
|||||||
protected:
|
protected:
|
||||||
interval_t m_interval{1.0};
|
interval_t m_interval{1.0};
|
||||||
};
|
};
|
||||||
}
|
} // namespace modules
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
Loading…
Reference in New Issue
Block a user