From 318965b71597b0617a893739d958e153a08faa00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 24 Sep 2020 14:32:39 +0200 Subject: [PATCH] module/clock: internally use either minutes or seconds granularity --- modules/clock.c | 58 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/modules/clock.c b/modules/clock.c index 0599e9a..2ff4f28 100644 --- a/modules/clock.c +++ b/modules/clock.c @@ -4,7 +4,10 @@ #include #include +#include +#define LOG_MODULE "clock" +#include "../log.h" #include "../bar/bar.h" #include "../config.h" #include "../config-verify.h" @@ -12,6 +15,10 @@ struct private { struct particle *label; + enum { + UPDATE_GRANULARITY_SECONDS, + UPDATE_GRANULARITY_MINUTES, + } update_granularity; char *date_format; char *time_format; }; @@ -55,20 +62,56 @@ content(struct module *mod) static int run(struct module *mod) { + const struct private *m = mod->private; const struct bar *bar = mod->bar; bar->refresh(bar); while (true) { - time_t now = time(NULL); - time_t now_no_secs = now / 60 * 60; - assert(now_no_secs % 60 == 0); + struct timespec _now; + clock_gettime(CLOCK_REALTIME, &_now); - time_t next_min = now_no_secs + 60; - time_t timeout = next_min - now; - assert(timeout >= 0 && timeout <= 60); + const struct timeval now = { + .tv_sec = _now.tv_sec, + .tv_usec = _now.tv_nsec / 1000, + }; + + int timeout_ms; + + switch (m->update_granularity) { + case UPDATE_GRANULARITY_SECONDS: { + const struct timeval next_second = { + .tv_sec = now.tv_sec + 1, + .tv_usec = 0}; + + struct timeval _timeout; + timersub(&next_second, &now, &_timeout); + + assert(_timeout.tv_sec == 0 || + (_timeout.tv_sec == 1 && _timeout.tv_usec == 0)); + timeout_ms = _timeout.tv_usec / 1000; + break; + } + + case UPDATE_GRANULARITY_MINUTES: { + const struct timeval next_minute = { + .tv_sec = now.tv_sec / 60 * 60 + 60, + .tv_usec = 0, + }; + + struct timeval _timeout; + timersub(&next_minute, &now, &_timeout); + timeout_ms = _timeout.tv_sec * 1000 + _timeout.tv_usec / 1000; + } + } + + /* Add 1ms to account for rounding errors */ + timeout_ms++; + + LOG_DBG("now: %lds %ldµs -> timeout: %dms", + now.tv_sec, now.tv_usec, timeout_ms); struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}}; - poll(fds, 1, timeout * 1000); + poll(fds, 1, timeout_ms); if (fds[0].revents & POLLIN) break; @@ -86,6 +129,7 @@ clock_new(struct particle *label, const char *date_format, const char *time_form m->label = label; m->date_format = strdup(date_format); m->time_format = strdup(time_format); + m->update_granularity = UPDATE_GRANULARITY_MINUTES; struct module *mod = module_common_new(); mod->private = m;