kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

timer.c (2531B)



      1 /*
      2  * Copyright (c) 2016-2022 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #include <sys/param.h>
     18 #include <sys/types.h>
     19 #include <sys/queue.h>
     20 
     21 #include "kore.h"
     22 
     23 TAILQ_HEAD(timerlist, kore_timer)	kore_timers;
     24 
     25 void
     26 kore_timer_init(void)
     27 {
     28 	TAILQ_INIT(&kore_timers);
     29 }
     30 
     31 struct kore_timer *
     32 kore_timer_add(void (*cb)(void *, u_int64_t), u_int64_t interval,
     33     void *arg, int flags)
     34 {
     35 	struct kore_timer	*timer, *t;
     36 
     37 	timer = kore_malloc(sizeof(*timer));
     38 
     39 	timer->cb = cb;
     40 	timer->arg = arg;
     41 	timer->flags = flags;
     42 	timer->interval = interval;
     43 	timer->nextrun = kore_time_ms() + timer->interval;
     44 
     45 	TAILQ_FOREACH(t, &kore_timers, list) {
     46 		if (t->nextrun > timer->nextrun) {
     47 			TAILQ_INSERT_BEFORE(t, timer, list);
     48 			return (timer);
     49 		}
     50 	}
     51 
     52 	TAILQ_INSERT_TAIL(&kore_timers, timer, list);
     53 	return (timer);
     54 }
     55 
     56 void
     57 kore_timer_remove(struct kore_timer *timer)
     58 {
     59 	TAILQ_REMOVE(&kore_timers, timer, list);
     60 	kore_free(timer);
     61 }
     62 
     63 u_int64_t
     64 kore_timer_next_run(u_int64_t now)
     65 {
     66 	struct kore_timer	*timer;
     67 
     68 	if ((timer = TAILQ_FIRST(&kore_timers)) != NULL) {
     69 		if (timer->nextrun > now)
     70 			return (timer->nextrun - now);
     71 		return (0);
     72 	}
     73 
     74 	return (KORE_WAIT_INFINITE);
     75 }
     76 
     77 void
     78 kore_timer_run(u_int64_t now)
     79 {
     80 	struct kore_timer	*timer, *t, *prev;
     81 
     82 	prev = NULL;
     83 
     84 	while ((timer = TAILQ_FIRST(&kore_timers)) != NULL) {
     85 		if (timer == prev)
     86 			break;
     87 
     88 		if (timer->nextrun > now)
     89 			break;
     90 
     91 		TAILQ_REMOVE(&kore_timers, timer, list);
     92 		timer->cb(timer->arg, now);
     93 
     94 		if (timer->flags & KORE_TIMER_ONESHOT) {
     95 			kore_free(timer);
     96 		} else {
     97 			prev = timer;
     98 			timer->nextrun = now + timer->interval;
     99 			TAILQ_FOREACH(t, &kore_timers, list) {
    100 				if (t->nextrun > timer->nextrun) {
    101 					TAILQ_INSERT_BEFORE(t, timer, list);
    102 					break;
    103 				}
    104 			}
    105 
    106 			if (t == NULL)
    107 				TAILQ_INSERT_TAIL(&kore_timers, timer, list);
    108 		}
    109 	}
    110 }