aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/hicn/base/loop.c
diff options
context:
space:
mode:
authorMauro Sardara <msardara@cisco.com>2020-07-29 09:05:08 +0200
committerMauro Sardara <msardara@cisco.com>2020-09-09 11:08:44 +0200
commitaba0a8ce4aeae0392b71658e9afaedc0d857a1a7 (patch)
tree739c9b88fd6696a992893c4f4d1c2af7c100032d /hicn-light/src/hicn/base/loop.c
parentd5071d0c80e1da5e28c2430ba4b579b886373cd2 (diff)
[HICN-555] Reworked loop
Signed-off-by: Mauro Sardara <msardara@cisco.com> Change-Id: Ia837da43b797a3f4d30d832e7ad2b0ec8cc3fefe Signed-off-by: Mauro Sardara <msardara@cisco.com>
Diffstat (limited to 'hicn-light/src/hicn/base/loop.c')
-rw-r--r--hicn-light/src/hicn/base/loop.c341
1 files changed, 97 insertions, 244 deletions
diff --git a/hicn-light/src/hicn/base/loop.c b/hicn-light/src/hicn/base/loop.c
index fecab9c5f..34aa94d6e 100644
--- a/hicn-light/src/hicn/base/loop.c
+++ b/hicn-light/src/hicn/base/loop.c
@@ -20,51 +20,57 @@
#include <assert.h>
#include <event2/event.h>
+#include <event2/event_struct.h>
#include <event2/thread.h>
-#include <fcntl.h> // fcntl
+#include <fcntl.h> // fcntl
#ifdef WITH_THREAD
#include <pthread.h>
#endif /* WITH_THREAD */
-#include <stdlib.h>
-#include <sys/timerfd.h>
-#include <unistd.h> // fcntl
-
#include <hicn/util/log.h>
-#include <hicn/util/map.h>
+#include <stdlib.h>
+#include <unistd.h> // fcntl
#include "loop.h"
-loop_t * MAIN_LOOP = NULL;
+loop_t *MAIN_LOOP = NULL;
/**
* \brief Holds all callback parameters
*/
typedef struct {
- void * owner;
+ void *owner;
fd_callback_t callback;
- void * data;
+ void *data;
} cb_wrapper_args_t;
-TYPEDEF_MAP_H(event_map, int, struct event *);
-TYPEDEF_MAP(event_map, int, struct event *, int_cmp, int_snprintf, generic_snprintf);
-
-/* Map that associates timer fds with their associated cb_wrapper_args_t */
-TYPEDEF_MAP_H(timer_fd_map, int, cb_wrapper_args_t *);
-TYPEDEF_MAP(timer_fd_map, int, cb_wrapper_args_t *, int_cmp, int_snprintf, generic_snprintf);
+typedef enum {
+ EVTYPE_TIMER,
+ EVTYPE_FD,
+} event_type_t;
struct loop_s {
- struct event_base * event_base;
- event_map_t * event_map;
- timer_fd_map_t * timer_fd_map;
-#ifdef WITH_THREAD
- pthread_t thread;
-#endif /* WITH_THREAD */
+ /* Libevent-based implementation */
+ struct event_base *event_base;
+};
+
+struct event_s {
+ /* Reference to loop */
+ loop_t *loop;
+
+ /* Event type*/
+ event_type_t event_type;
+
+ /* Raw event */
+ struct event raw_event;
+
+ /* Callback on event */
+ cb_wrapper_args_t callback;
};
-loop_t *
-loop_create()
+loop_t *loop_create()
{
- loop_t * loop = malloc(sizeof(loop_t));
+ loop_t *loop = malloc(sizeof(loop_t));
+
if (!loop) {
ERROR("[loop_create] Failed to allocate memory");
goto ERR_MALLOC;
@@ -75,281 +81,128 @@ loop_create()
#endif /* WITH_THREAD */
loop->event_base = event_base_new();
- if (!loop)
- goto ERR_EVENT;
-
- loop->event_map = event_map_create();
- if (!loop->event_map) {
- ERROR("[loop_create] Failed to create event_map");
- goto ERR_EVENT_MAP;
- }
-
- loop->timer_fd_map = timer_fd_map_create();
- if (!loop->timer_fd_map) {
- ERROR("[loop_create] Failed to create timer_fd_map");
- goto ERR_TIMER_FD_MAP;
- }
+ if (!loop->event_base) goto ERR_EVENT;
event_set_log_callback(NULL);
return loop;
- timer_fd_map_free(loop->timer_fd_map);
-ERR_TIMER_FD_MAP:
- event_map_free(loop->event_map);
-ERR_EVENT_MAP:
- event_base_free(loop->event_base);
ERR_EVENT:
- free(loop);
ERR_MALLOC:
return NULL;
}
-void
-loop_free(loop_t * loop)
-{
- /*
- * Release all timer cb_wrapper_args_t
- *
- * We need to stop all timers, this should release associated fd events at
- * the same time... for that reason, this code has to be called before
- * releasing events
- */
-
- int * timer_fd_map_array;
- int n = timer_fd_map_get_key_array(loop->timer_fd_map, &timer_fd_map_array);
- if (n < 0) {
- ERROR("[loop_free] Could not get event map array");
- } else {
- for (unsigned i = 0; i < n; i++) {
- int fd = timer_fd_map_array[i];
- if (loop_unregister_timer(loop, fd) < 0) {
- ERROR("[loop_free] Could not unregister timer");
- }
- }
- free(timer_fd_map_array);
- }
- timer_fd_map_free(loop->timer_fd_map);
-
- /* Release all events */
+void loop_free(loop_t *loop) { event_base_free(loop->event_base); }
- int * event_map_array;
- n = event_map_get_key_array(loop->event_map, &event_map_array);
- if (n < 0) {
- ERROR("[loop_free] Could not get event map array");
- } else {
- for (unsigned i = 0; i < n; i++) {
- int fd = event_map_array[i];
- if (loop_unregister_fd(loop, fd) < 0) {
- ERROR("[loop_free] Could not unregister fd");
- }
- }
- free(event_map_array);
- }
- event_map_free(loop->event_map);
-
- event_base_free(loop->event_base);
-
- free(loop);
-}
-
-int
-loop_dispatch(loop_t * loop)
+int loop_dispatch(loop_t *loop)
{
-#ifdef WITH_THREAD
- if (pthread_create(&loop->thread, NULL, (void * (*)(void *))event_base_dispatch, loop->event_base)) {
- fprintf(stderr, "Error creating thread\n");
- return -1;
- }
-#else
- event_base_dispatch(loop->event_base);
-#endif /* WITH_THREAD */
+ event_base_loop(loop->event_base, 0);
return 0;
}
-int
-loop_undispatch(loop_t * loop)
-{
-#ifdef WITH_THREAD
- DEBUG("Waiting for loop to terminate...");
- if(pthread_join(loop->thread, NULL)) {
- fprintf(stderr, "Error joining thread\n");
- return -1;
- }
- DEBUG("Loop terminated !");
-#endif /* WITH_THREAD */
- return 0;
-}
+int loop_undispatch(loop_t *loop) { return 0; }
-void
-loop_break(loop_t * loop)
-{
- event_base_loopbreak(loop->event_base);
-}
+void loop_break(loop_t *loop) { event_base_loopbreak(loop->event_base); }
-void cb_wrapper(evutil_socket_t fd, short what, void * arg) {
- cb_wrapper_args_t * cb_wrapper_args = arg;
- cb_wrapper_args->callback(cb_wrapper_args->owner, fd, cb_wrapper_args->data);
+void cb_wrapper(evutil_socket_t fd, short what, void *arg)
+{
+ cb_wrapper_args_t *cb_wrapper_args = arg;
+ cb_wrapper_args->callback(cb_wrapper_args->owner, fd,
+ cb_wrapper_args->data);
}
-int
-loop_register_fd(loop_t * loop, int fd, void * callback_owner,
- fd_callback_t callback, void * callback_data)
+static inline void _event_create(event_t **event, loop_t *loop,
+ event_type_t type, void *callback_owner,
+ fd_callback_t callback, void *callback_data)
{
- /* This will be freed with the event */
- cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
- *cb_wrapper_args = (cb_wrapper_args_t) {
+ *event = malloc(sizeof(event_t));
+ (*event)->callback = (cb_wrapper_args_t){
.owner = callback_owner,
.callback = callback,
.data = callback_data,
};
+ (*event)->event_type = type;
+ (*event)->loop = loop;
+}
+
+int loop_fd_event_create(event_t **event, loop_t *loop, int fd,
+ void *callback_owner, fd_callback_t callback,
+ void *callback_data)
+{
+ _event_create(event, loop, EVTYPE_FD, callback_owner, callback,
+ callback_data);
evutil_make_socket_nonblocking(fd);
- struct event * event = event_new(loop->event_base, fd, EV_READ | EV_PERSIST, cb_wrapper, cb_wrapper_args);
- if (!event) {
- ERROR("[loop_register_fd] event_new");
- goto ERR_EVENT_NEW;
- }
+ event_assign(&(*event)->raw_event, loop->event_base, fd,
+ EV_READ | EV_PERSIST, cb_wrapper, &(*event)->callback);
+
+ return 0;
+}
+
+int loop_fd_event_register(event_t *event)
+{
+ assert(event->event_type == EVTYPE_FD);
- if (event_add(event, NULL) < 0) {
+ if (event_add(&event->raw_event, NULL) < 0) {
ERROR("[loop_register_fd] event_add");
goto ERR_EVENT_ADD;
}
- if (event_map_add(loop->event_map, fd, event) < 0) {
- ERROR("[loop_register_fd] event_map_add");
- goto ERR_EVENT_MAP;
- }
-
return 0;
-ERR_EVENT_MAP:
ERR_EVENT_ADD:
- event_free(event);
-ERR_EVENT_NEW:
return -1;
}
-int
-loop_unregister_fd(loop_t * loop, int fd)
+int loop_event_unregister(event_t *event)
{
- struct event * event = NULL;
-
- if (event_map_remove(loop->event_map, fd, &event) < 0) {
- ERROR("[loop_unregister_fd] Error removing event associated to fd");
- return -1;
- }
-
- assert(event);
-
- cb_wrapper_args_t * cb_wrapper_args = event_get_callback_arg(event);
- free(cb_wrapper_args);
-
- event_del(event);
- event_free(event);
-
+ assert(event->event_type == EVTYPE_FD);
+ event_del(&event->raw_event);
return 0;
}
-int
-loop_timer_callback(loop_t * loop, int fd, void * data)
+int loop_timer_create(event_t **timer, loop_t *loop, void *callback_owner,
+ fd_callback_t callback, void *callback_data)
{
- char buf[1024]; /* size is not important */
- cb_wrapper_args_t * cb_wrapper_args = data;
- while (read(fd, &buf, sizeof(buf)) > 0)
- ;
+ _event_create(timer, loop, EVTYPE_TIMER, callback_owner, callback,
+ callback_data);
- int rc = cb_wrapper_args->callback(cb_wrapper_args->owner, fd,
- cb_wrapper_args->data);
+ evtimer_assign(&(*timer)->raw_event, loop->event_base, cb_wrapper,
+ &(*timer)->callback);
- return rc;
+ return 0;
}
-int
-_loop_register_timer(loop_t * loop, unsigned delay_ms, void * owner,
- fd_callback_t callback, void * data)
+static inline void _ms_to_timeval(unsigned delay_ms, struct timeval *tv)
{
- int fd = timerfd_create(CLOCK_MONOTONIC, 0);
- if (fd == -1) {
- perror("timerfd_create");
- return -1;
- }
-
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
- perror("fcntl");
- return -1;
- }
-
- struct itimerspec ts = {
- .it_interval = {
- .tv_sec = delay_ms / 1000,
- .tv_nsec = (delay_ms % 1000) * 1000000,
- },
- .it_value = {
- .tv_sec = delay_ms / 1000,
- .tv_nsec = (delay_ms % 1000) * 1000000,
- }
- };
-
- if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
- perror("timerfd_settime");
- return -1;
- }
+ tv->tv_sec = delay_ms / 1000;
+ tv->tv_usec = (delay_ms % 1000) * 1000;
+}
- /* This should be freed together with the timer release */
- cb_wrapper_args_t * cb_wrapper_args = malloc(sizeof(cb_wrapper_args_t));
- *cb_wrapper_args = (cb_wrapper_args_t) {
- .owner = owner,
- .callback = callback,
- .data = data,
- };
+int loop_timer_register(event_t *timer, unsigned delay_ms)
+{
+ assert(timer->event_type == EVTYPE_TIMER);
- if (timer_fd_map_add(loop->timer_fd_map, fd, cb_wrapper_args) < 0) {
- ERROR("[loop_register_timer] Could not add cb_wrapper to timer map");
- return -1;
- }
+ struct timeval tv;
+ _ms_to_timeval(delay_ms, &tv);
- if (loop_register_fd(loop, fd, loop,
- (fd_callback_t) loop_timer_callback, cb_wrapper_args) < 0) {
- ERROR("[loop_register_timer] Error registering fd to event loop");
- return -1;
+ if (tv.tv_sec == 0 && tv.tv_usec == 0) {
+ event_active(&timer->raw_event, EV_TIMEOUT, 0);
+ } else {
+ event_add(&timer->raw_event, &tv);
}
- return fd;
+ return 0;
}
-int
-loop_unregister_timer(loop_t * loop, int fd)
+int loop_timer_is_enabled(event_t *timer)
{
- struct itimerspec ts = {
- .it_interval = {
- .tv_sec = 0,
- .tv_nsec = 0,
- },
- .it_value = { /* This value disables the timer */
- .tv_sec = 0,
- .tv_nsec = 0,
- }
- };
- ts.it_value.tv_sec = 0;
-
- if (timerfd_settime(fd, 0, &ts, NULL) == -1) {
- perror("timerfd_settime");
- return -1;
- }
-
- cb_wrapper_args_t * cb_wrapper_args;
- if (timer_fd_map_remove(loop->timer_fd_map, fd, &cb_wrapper_args) < 0) {
- ERROR("[loop_unregister_timer] Could not remove cb_wrapper from timer map");
- return -1;
- }
- assert(cb_wrapper_args);
- free(cb_wrapper_args);
-
- if (loop_unregister_fd(loop, fd) < 0) {
- ERROR("[loop_unregister_timer] Error unregistering fd from event loop");
- return -1;
- }
+ return evtimer_pending(&timer->raw_event, NULL) != 0;
+}
+int loop_event_free(event_t *event)
+{
+ loop_event_unregister(event);
+ free(event);
return 0;
}