Files
rtbrick-bngblaster/code/common/src/timer.h
T

105 lines
2.9 KiB
C
Raw Normal View History

2021-02-04 21:56:56 +01:00
/*
2022-03-08 16:51:41 +01:00
* A O(1) Timer library
2021-02-04 21:56:56 +01:00
*
* Hannes Gredler, July 2020
*
2022-03-08 16:51:41 +01:00
* Copyright (C) 2020-2022, RtBrick, Inc.
* SPDX-License-Identifier: BSD-3-Clause
2021-02-04 21:56:56 +01:00
*/
2022-03-08 16:51:41 +01:00
#ifndef __COMMON_TIMER_H__
#define __COMMON_TIMER_H__
#include "common.h"
2021-02-04 21:56:56 +01:00
2021-10-21 11:20:34 +02:00
#define MSEC 1000000 /* 1 million nanoseconds == 1 msec */
#define SEC 1000000000 /* 1 billion nanoseconds == 1 sec */
2021-02-04 21:56:56 +01:00
2022-03-08 16:51:41 +01:00
/* Top level data structure for timers. */
2021-02-04 21:56:56 +01:00
typedef struct timer_root_
{
CIRCLEQ_HEAD(timer_bucket_root_, timer_bucket_ ) timer_bucket_qhead; /* Bucket list */
CIRCLEQ_HEAD(timer_gc_root_, timer_ ) timer_gc_qhead; /* Garbage collection list */
CIRCLEQ_HEAD(timer_change_root_, timer_ ) timer_change_qhead; /* Change timers list */
2022-03-08 16:51:41 +01:00
uint32_t buckets; /* # of buckets hanging off */
uint32_t gc; /* # of timers waiting for GC */
2021-02-04 21:56:56 +01:00
} timer_root_s;
2022-03-08 16:51:41 +01:00
/* Group each like timers (e.g. all 100ms, 1s, 5s timers) into a timer bucket.
2021-02-04 21:56:56 +01:00
* All buckets hang off the timer root.
* Since time does not run backwards, timer insertion becomes a O(1) operation as one needs
2022-03-08 16:51:41 +01:00
* only to locate the appropriate bucket and insert at the tail of the per bucket queue. */
2021-02-04 21:56:56 +01:00
typedef struct timer_bucket_
{
CIRCLEQ_HEAD(timer_bucket_head_, timer_ ) timer_qhead; /* head of timers */
CIRCLEQ_ENTRY(timer_bucket_) timer_bucket_qnode; /* node in bucket list */
struct timer_root_ *timer_root; /* back pointer */
time_t sec;
long nsec;
2022-03-08 16:51:41 +01:00
uint32_t timers; /* # of timers hanging off this bucket */
2021-02-04 21:56:56 +01:00
} timer_bucket_s;
2022-03-08 16:51:41 +01:00
/* Timer which hangs off the bucket list. */
2021-02-04 21:56:56 +01:00
typedef struct timer_
{
CIRCLEQ_ENTRY(timer_) timer_qnode;
CIRCLEQ_ENTRY(timer_) timer_change_qnode;
2022-09-15 16:21:57 +00:00
struct timespec expire; /* expiration interval */
2022-11-01 10:33:26 +00:00
struct timespec *timestamp;
2022-09-15 16:21:57 +00:00
struct timer_bucket_ *timer_bucket; /* back pointer */
struct timer_ **ptimer; /* where this timer pointer gets stored */
2022-03-08 16:51:41 +01:00
void *data; /* misc. data */
void (*cb)(struct timer_ *); /* callback function. */
bool expired;
bool periodic; /* auto restart timer ? */
2022-10-14 16:28:57 +02:00
bool reset; /* reset reference/start time */
bool delete; /* timer has been deleted */
bool on_change_list; /* node is on change list */
2022-09-15 16:21:57 +00:00
char name[32];
} timer_s;
2021-02-04 21:56:56 +01:00
2022-09-15 16:21:57 +00:00
/* Public API */
2022-03-08 16:51:41 +01:00
2022-09-15 16:21:57 +00:00
void
timespec_add(struct timespec *, struct timespec *, struct timespec *);
2021-02-04 21:56:56 +01:00
2022-09-15 16:21:57 +00:00
void
timespec_sub(struct timespec *, struct timespec *, struct timespec *);
char *
timespec_format(struct timespec *x);
void
timer_smear_bucket(timer_root_s *, time_t, long);
void
timer_smear_all_buckets(timer_root_s *root);
void
timer_del(timer_s *);
void
timer_add(timer_root_s *root, timer_s **ptimer, char *name,
time_t sec, long nsec,
void *data, void (*cb)(timer_s *));
void
timer_add_periodic(timer_root_s *root, timer_s **ptimer, char *name,
time_t sec, long nsec,
void *data, void (*cb)(timer_s *));
void
timer_walk(timer_root_s *root);
void
timer_init_root(timer_root_s *timer_root);
2022-03-08 16:51:41 +01:00
2022-09-15 16:21:57 +00:00
void
timer_flush_root(timer_root_s *timer_root);
2021-02-04 21:56:56 +01:00
2022-03-08 16:51:41 +01:00
#endif /* __TIMER_H__ */