93 lines
2.5 KiB
C
93 lines
2.5 KiB
C
|
#include "timer.h"
|
||
|
|
||
|
struct timer_ctx {
|
||
|
timer_cb cb;
|
||
|
void* user_ctx;
|
||
|
};
|
||
|
|
||
|
void free_timerctx(void* c) {
|
||
|
free(c);
|
||
|
}
|
||
|
|
||
|
int set_timeout_handle(struct evt_core_ctx* ctx, struct evt_core_fdinfo* fdinfo) {
|
||
|
uint64_t ctr;
|
||
|
ssize_t tmr_rd;
|
||
|
tmr_rd = read(fdinfo->fd, &ctr, sizeof(ctr));
|
||
|
if (tmr_rd == -1 && errno == EAGAIN) return 1;
|
||
|
if (tmr_rd < 0) {
|
||
|
perror("read on timer");
|
||
|
fprintf(stderr, "An error occured on timer fd=%d\n", fdinfo->fd);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
struct timer_ctx* tctx = fdinfo->other;
|
||
|
tctx->cb(ctx, tctx->user_ctx);
|
||
|
|
||
|
evt_core_rm_fd(ctx, fdinfo->fd);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void init_timer(struct evt_core_ctx* evts) {
|
||
|
struct evt_core_cat* cat = evt_core_get_from_cat (evts, "set_timeout");
|
||
|
if (cat != NULL) {
|
||
|
fprintf(stderr, "timeout category has already been registered\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
struct evt_core_cat timer = {
|
||
|
.name = "set_timeout",
|
||
|
.flags = EPOLLIN | EPOLLET,
|
||
|
.app_ctx = NULL,
|
||
|
.free_app_ctx = NULL,
|
||
|
.cb = set_timeout_handle,
|
||
|
.err_cb = NULL
|
||
|
};
|
||
|
evt_core_add_cat(evts, &timer);
|
||
|
}
|
||
|
|
||
|
int set_timeout(struct evt_core_ctx* evts, uint64_t milli_sec, void* ctx, timer_cb cb) {
|
||
|
struct timespec now;
|
||
|
struct itimerspec timer_config;
|
||
|
char url[1024];
|
||
|
struct evt_core_cat cat = {0};
|
||
|
struct evt_core_fdinfo fdinfo = {0};
|
||
|
fdinfo.cat = &cat;
|
||
|
fdinfo.url = url;
|
||
|
|
||
|
//printf("Will add a timeout of %ld ms\n", milli_sec);
|
||
|
if (clock_gettime(CLOCK_REALTIME, &now) == -1) {
|
||
|
perror("clock_gettime");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
uint64_t ns = now.tv_nsec + (milli_sec % 1000) * 1000000;
|
||
|
timer_config.it_value.tv_sec = now.tv_sec + milli_sec / 1000 + ns / 1000000000;
|
||
|
timer_config.it_value.tv_nsec = ns % 1000000000;
|
||
|
timer_config.it_interval.tv_sec = 60;
|
||
|
timer_config.it_interval.tv_nsec = 0;
|
||
|
|
||
|
fdinfo.fd = timerfd_create(CLOCK_REALTIME, 0);
|
||
|
if (fdinfo.fd == -1) {
|
||
|
perror("Unable to timerfd_create");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
if (timerfd_settime (fdinfo.fd, TFD_TIMER_ABSTIME, &timer_config, NULL) == -1) {
|
||
|
perror("Unable to timerfd_settime");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
fdinfo.cat->name = "set_timeout";
|
||
|
struct timer_ctx* tctx = malloc(sizeof(struct timer_ctx)); // Should put the link number and the id
|
||
|
if (tctx == NULL) {
|
||
|
perror("malloc failed in set_timeout");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
tctx->user_ctx = ctx;
|
||
|
tctx->cb = cb;
|
||
|
fdinfo.other = tctx;
|
||
|
fdinfo.free_other = free_timerctx;
|
||
|
sprintf(fdinfo.url, "timer:%ld:1", milli_sec);
|
||
|
evt_core_add_fd (evts, &fdinfo);
|
||
|
|
||
|
return fdinfo.fd;
|
||
|
}
|