aboutsummaryrefslogtreecommitdiff
path: root/src/timer.c
diff options
context:
space:
mode:
authorPhilip Wittamore <philip@wittamore.com>2025-06-08 22:00:43 +0200
committerPhilip Wittamore <philip@wittamore.com>2025-06-08 22:00:43 +0200
commit81757c235ff8e112b4baabdd1ff23409426e9c98 (patch)
treeef213566ac3c17bf3d7795b0597f254791bd219e /src/timer.c
downloaddwmblocks-async-81757c235ff8e112b4baabdd1ff23409426e9c98.tar.gz
dwmblocks-async-81757c235ff8e112b4baabdd1ff23409426e9c98.tar.bz2
dwmblocks-async-81757c235ff8e112b4baabdd1ff23409426e9c98.zip
update
Diffstat (limited to 'src/timer.c')
-rw-r--r--src/timer.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/timer.c b/src/timer.c
new file mode 100644
index 0000000..2ee555b
--- /dev/null
+++ b/src/timer.c
@@ -0,0 +1,72 @@
+#include "timer.h"
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "block.h"
+#include "util.h"
+
+static unsigned int compute_tick(const block *const blocks,
+ const unsigned short block_count) {
+ unsigned int tick = 0;
+
+ for (unsigned short i = 0; i < block_count; ++i) {
+ const block *const block = &blocks[i];
+ tick = gcd(block->interval, tick);
+ }
+
+ return tick;
+}
+
+static unsigned int compute_reset_value(const block *const blocks,
+ const unsigned short block_count) {
+ unsigned int reset_value = 1;
+
+ for (unsigned short i = 0; i < block_count; ++i) {
+ const block *const block = &blocks[i];
+ reset_value = MAX(block->interval, reset_value);
+ }
+
+ return reset_value;
+}
+
+timer timer_new(const block *const blocks, const unsigned short block_count) {
+ const unsigned int reset_value = compute_reset_value(blocks, block_count);
+
+ timer timer = {
+ .time = reset_value, // Initial value to execute all blocks.
+ .tick = compute_tick(blocks, block_count),
+ .reset_value = reset_value,
+ };
+
+ return timer;
+}
+
+int timer_arm(timer *const timer) {
+ errno = 0;
+ (void)alarm(timer->tick);
+
+ if (errno != 0) {
+ (void)fprintf(stderr, "error: could not arm timer\n");
+ return 1;
+ }
+
+ // Wrap `time` to the interval [1, reset_value].
+ timer->time = (timer->time + timer->tick) % timer->reset_value;
+
+ return 0;
+}
+
+bool timer_must_run_block(const timer *const timer, const block *const block) {
+ if (timer == NULL || timer->time == timer->reset_value) {
+ return true;
+ }
+
+ if (block->interval == 0) {
+ return false;
+ }
+
+ return timer->time % block->interval == 0;
+}