O2S C Library 1.8.2
Provide high-level data-structures and other fundamental tools for C projects
Loading...
Searching...
No Matches
timer.c
Go to the documentation of this file.
1/* ************************************************************************** */
2/* ____ _ _____ ____ _ _ _ _____ _ _ ____ ____ */
3/* / ___| / \ | ___| _ \ / \ | \ | | |_ _| || | | _ \/ ___| */
4/* \___ \ / _ \ | |_ | |_) | / _ \ | \| | | | | || |_| | | \___ \ */
5/* ___) / ___ \| _| | _ < / ___ \| |\ | | | |__ _| |_| |___) | */
6/* |____/_/ \_|_| |_| \_/_/ \_|_| \_| |_| |_| |____/|____/ */
7/* */
14/* ************************************************************************** */
15
16#define _GNU_SOURCE
17
18#include "o2s/timer.h"
19
20#include "o2s/log.h"
21
22#include <errno.h> // errno
23#include <iso646.h> // not
24#include <signal.h> // sigaction
25#include <string.h> // strerror
26#include <time.h> // timer_*
27#include <unistd.h> // gettid
28
30#define MS_IN_NS 1000000UL
31
33#define MS_PER_S 1000
34
40bool o2s_timer_setup_process(void (*handle)(int, siginfo_t*, void*))
41{
42 struct sigaction signal_action;
43
44 sigemptyset(&signal_action.sa_mask);
45 signal_action.sa_sigaction = handle;
46 signal_action.sa_flags = SA_SIGINFO;
47 if (sigaction(SIGALRM, &signal_action, NULL) == 0)
48 return true;
49 log_error("Unable to set signal action: %s", strerror(errno));
50 return false;
51}
52
60{
61 o2s_timer_t timer;
62 struct sigevent event = {
63 .sigev_notify = SIGEV_THREAD_ID,
64 .sigev_signo = SIGALRM,
65#ifdef __USE_GNU
66 ._sigev_un._tid = gettid(),
67#else
68 .sigev_notify_thread_id = gettid(),
69#endif
70 };
71
72 timer.created = (timer_create(CLOCK_REALTIME, &event, &timer.timer_id) == 0);
73 if (not timer.created)
74 log_error("Unable to create a timer: %s", strerror(errno));
75 return timer;
76}
77
82o2s_timer_t o2s_timer_start(o2s_timer_t timer, unsigned milliseconds)
83{
84 struct itimerspec duration = {
85 .it_value.tv_nsec = MS_IN_NS * (milliseconds % MS_PER_S),
86 .it_value.tv_sec = milliseconds / MS_PER_S,
87 };
88
89 timer.armed = (timer_settime(timer.timer_id, 0, &duration, NULL) == 0);
90 if (not timer.armed)
91 log_error("Unable to arm timer: %s", strerror(errno));
92 return timer;
93}
94
97{
98 struct itimerspec duration = {0};
99
100 if (not timer->armed)
101 {
102 log_debug("No need to disarm a disarmed timer");
103 return;
104 }
105 if (timer_settime(timer->timer_id, 0, &duration, NULL) == 0)
106 return;
107 log_error("Unable to disarm timer: %s", strerror(errno));
108}
109
112{
113 if (not timer->created)
114 {
115 log_debug("No need to delete a non-created timer");
116 return;
117 }
118 if (timer_delete(timer->timer_id) == 0)
119 return;
120 log_error("Unable to delete timer: %s", strerror(errno));
121}
Simplistic logging utilities.
#define log_error(...)
Report a condition causing the current operation to abort.
Definition log.h:83
#define log_debug(...)
Report information useful to the developer.
Definition log.h:64
Dynamic string implementation.
#define MS_PER_S
Number of milli-seconds in a second.
Definition timer.c:33
bool o2s_timer_setup_process(void(*handle)(int, siginfo_t *, void *))
Prepare the process for timeouts.
Definition timer.c:40
#define MS_IN_NS
Milli-seconds expressed in nano-seconds.
Definition timer.c:30
o2s_timer_t o2s_timer_start(o2s_timer_t timer, unsigned milliseconds)
Arm timer for the specified duration, in milliseconds.
Definition timer.c:82
void o2s_timer_stop(o2s_timer_t *timer)
Disarm timer.
Definition timer.c:96
o2s_timer_t o2s_timer_create()
Initialize a timer, that will create a SIGALRM in the current thread when timing out.
Definition timer.c:59
void o2s_timer_delete(o2s_timer_t *timer)
Destructor.
Definition timer.c:111
Use timeouts backed by signals and realtime clock.