timer.c (1814B)
1 #include "timer.h" 2 3 #include <errno.h> 4 #include <stdbool.h> 5 #include <stdio.h> 6 #include <unistd.h> 7 8 #include "block.h" 9 #include "util.h" 10 11 static unsigned int compute_tick(const block *const blocks, 12 const unsigned short block_count) { 13 unsigned int tick = 0; 14 15 for (unsigned short i = 0; i < block_count; ++i) { 16 const block *const block = &blocks[i]; 17 tick = gcd(block->interval, tick); 18 } 19 20 return tick; 21 } 22 23 static unsigned int compute_reset_value(const block *const blocks, 24 const unsigned short block_count) { 25 unsigned int reset_value = 1; 26 27 for (unsigned short i = 0; i < block_count; ++i) { 28 const block *const block = &blocks[i]; 29 reset_value = MAX(block->interval, reset_value); 30 } 31 32 return reset_value; 33 } 34 35 timer timer_new(const block *const blocks, const unsigned short block_count) { 36 const unsigned int reset_value = compute_reset_value(blocks, block_count); 37 38 timer timer = { 39 .time = reset_value, // Initial value to execute all blocks. 40 .tick = compute_tick(blocks, block_count), 41 .reset_value = reset_value, 42 }; 43 44 return timer; 45 } 46 47 int timer_arm(timer *const timer) { 48 errno = 0; 49 (void)alarm(timer->tick); 50 51 if (errno != 0) { 52 (void)fprintf(stderr, "error: could not arm timer\n"); 53 return 1; 54 } 55 56 // Wrap `time` to the interval [1, reset_value]. 57 timer->time = (timer->time + timer->tick) % timer->reset_value; 58 59 return 0; 60 } 61 62 bool timer_must_run_block(const timer *const timer, const block *const block) { 63 if (timer == NULL || timer->time == timer->reset_value) { 64 return true; 65 } 66 67 if (block->interval == 0) { 68 return false; 69 } 70 71 return timer->time % block->interval == 0; 72 }