mongoose/src/timer.c

41 lines
1.5 KiB
C

#include "timer.h"
#include "arch.h"
#define MG_TIMER_CALLED 4
void mg_timer_init(struct mg_timer **head, struct mg_timer *t, uint64_t ms,
unsigned flags, void (*fn)(void *), void *arg) {
t->id = 0, t->period_ms = ms, t->expire = 0;
t->flags = flags, t->fn = fn, t->arg = arg, t->next = *head;
*head = t;
}
void mg_timer_free(struct mg_timer **head, struct mg_timer *t) {
while (*head && *head != t) head = &(*head)->next;
if (*head) *head = t->next;
}
// t: expiration time, prd: period, now: current time. Return true if expired
bool mg_timer_expired(uint64_t *t, uint64_t prd, uint64_t now) {
if (now + prd < *t) *t = 0; // Time wrapped? Reset timer
if (*t == 0) *t = now + prd; // Firt poll? Set expiration
if (*t > now) return false; // Not expired yet, return
*t = (now - *t) > prd ? now + prd : *t + prd; // Next expiration time
return true; // Expired, return true
}
void mg_timer_poll(struct mg_timer **head, uint64_t now_ms) {
struct mg_timer *t, *tmp;
for (t = *head; t != NULL; t = tmp) {
bool once = t->expire == 0 && (t->flags & MG_TIMER_RUN_NOW) &&
!(t->flags & MG_TIMER_CALLED); // Handle MG_TIMER_NOW only once
bool expired = mg_timer_expired(&t->expire, t->period_ms, now_ms);
tmp = t->next;
if (!once && !expired) continue;
if ((t->flags & MG_TIMER_REPEAT) || !(t->flags & MG_TIMER_CALLED)) {
t->fn(t->arg);
}
t->flags |= MG_TIMER_CALLED;
}
}