generic wrapper for event libraries
https://redmine.lighttpd.net/projects/evcon
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
4.3 KiB
165 lines
4.3 KiB
|
|
#include <evcon-ev.h>
|
|
|
|
#include <evcon-allocator.h>
|
|
#include <evcon-backend.h>
|
|
|
|
#include <evcon-config-private.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#define UNUSED(x) ((void)(x))
|
|
|
|
/* ev loop wrapper */
|
|
|
|
static void evcon_ev_free_loop(evcon_loop *loop, void *loop_data, void *backend_data) {
|
|
UNUSED(loop);
|
|
UNUSED(backend_data);
|
|
UNUSED(loop_data);
|
|
}
|
|
|
|
static void evcon_ev_fd_cb(struct ev_loop *loop, ev_io *w, int revents) {
|
|
evcon_fd_watcher *watcher = (evcon_fd_watcher*) w->data;
|
|
int events;
|
|
UNUSED(loop);
|
|
|
|
events = 0;
|
|
if (0 != (revents & EV_ERROR)) events |= EVCON_ERROR;
|
|
if (0 != (revents & EV_READ)) events |= EVCON_READ;
|
|
if (0 != (revents & EV_WRITE)) events |= EVCON_WRITE;
|
|
|
|
evcon_feed_fd(watcher, events);
|
|
}
|
|
|
|
static void evcon_ev_fd_update(evcon_fd_watcher *watcher, evcon_fd fd, int events, evcon_allocator *allocator, void *loop_data, void *watcher_data) {
|
|
ev_io *w = (ev_io*) watcher_data;
|
|
struct ev_loop *evl = (struct ev_loop*) loop_data;
|
|
int evs;
|
|
|
|
if (-1 == fd) {
|
|
/* delete watcher */
|
|
if (NULL == w) return;
|
|
|
|
ev_io_stop(evl, w);
|
|
evcon_free(allocator, w, sizeof(*w));
|
|
evcon_fd_set_backend_data(watcher, NULL);
|
|
return;
|
|
}
|
|
|
|
evs = 0;
|
|
if (0 != (events & EVCON_READ)) evs |= EV_READ;
|
|
if (0 != (events & EVCON_WRITE)) evs |= EV_WRITE;
|
|
|
|
if (NULL == w) {
|
|
w = evcon_alloc0(allocator, sizeof(ev_io));
|
|
evcon_fd_set_backend_data(watcher, w);
|
|
ev_io_init(w, evcon_ev_fd_cb, fd, evs);
|
|
w->data = watcher;
|
|
if (0 != evs) ev_io_start(evl, w);
|
|
return;
|
|
}
|
|
|
|
if (w->events == evs && fd == w->fd) return;
|
|
|
|
ev_io_stop(evl, w);
|
|
ev_io_set(w, fd, evs);
|
|
if (0 != evs) ev_io_start(evl, w);
|
|
}
|
|
|
|
static void evcon_ev_timer_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|
evcon_timer_watcher *watcher = (evcon_timer_watcher*) w->data;
|
|
UNUSED(loop);
|
|
UNUSED(revents);
|
|
|
|
evcon_feed_timer(watcher);
|
|
}
|
|
|
|
static void evcon_ev_timer_update(evcon_timer_watcher *watcher, evcon_interval timeout, evcon_allocator *allocator, void *loop_data, void *watcher_data) {
|
|
ev_timer *w = (ev_timer*) watcher_data;
|
|
struct ev_loop *evl = (struct ev_loop*) loop_data;
|
|
|
|
if (-2 == timeout) {
|
|
/* delete watcher */
|
|
if (NULL == w) return;
|
|
|
|
ev_timer_stop(evl, w);
|
|
evcon_free(allocator, w, sizeof(*w));
|
|
evcon_timer_set_backend_data(watcher, NULL);
|
|
return;
|
|
}
|
|
|
|
if (-1 == timeout && NULL == w) return;
|
|
|
|
if (-1 == timeout) {
|
|
ev_timer_stop(evl, w);
|
|
return;
|
|
}
|
|
|
|
if (NULL == w) {
|
|
w = evcon_alloc0(allocator, sizeof(ev_timer));
|
|
evcon_timer_set_backend_data(watcher, w);
|
|
ev_timer_init(w, evcon_ev_timer_cb, EVCON_INTERVAL_AS_DOUBLE_SEC(timeout), 0.);
|
|
w->data = watcher;
|
|
ev_timer_start(evl, w);
|
|
return;
|
|
}
|
|
|
|
ev_timer_stop(evl, w);
|
|
ev_timer_set(w, EVCON_INTERVAL_AS_DOUBLE_SEC(timeout), 0.);
|
|
ev_timer_start(evl, w);
|
|
}
|
|
|
|
static void evcon_ev_async_cb(struct ev_loop *loop, ev_async *w, int revents) {
|
|
evcon_async_watcher *watcher = (evcon_async_watcher*) w->data;
|
|
UNUSED(loop);
|
|
UNUSED(revents);
|
|
|
|
evcon_feed_async(watcher);
|
|
}
|
|
|
|
static void evcon_ev_async_update(evcon_async_watcher *watcher, evcon_async_func f, evcon_allocator *allocator, void *loop_data, void *watcher_data) {
|
|
ev_async *w = (ev_async*) watcher_data;
|
|
struct ev_loop *evl = (struct ev_loop*) loop_data;
|
|
|
|
switch (f) {
|
|
case EVCON_ASYNC_TRIGGER:
|
|
ev_async_send(evl, w);
|
|
break;
|
|
case EVCON_ASYNC_NEW:
|
|
w = evcon_alloc0(allocator, sizeof(ev_async));
|
|
evcon_async_set_backend_data(watcher, w);
|
|
ev_async_init(w, evcon_ev_async_cb);
|
|
w->data = watcher;
|
|
ev_async_start(evl, w);
|
|
break;
|
|
case EVCON_ASYNC_FREE:
|
|
if (NULL == w) return;
|
|
|
|
ev_async_stop(evl, w);
|
|
evcon_free(allocator, w, sizeof(*w));
|
|
evcon_async_set_backend_data(watcher, NULL);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static evcon_backend* evcon_ev_backend(evcon_allocator* allocator) {
|
|
static char static_backend_buf[EVCON_BACKEND_RECOMMENDED_SIZE];
|
|
static volatile evcon_backend* backend = NULL;
|
|
|
|
if (g_once_init_enter(&backend)) {
|
|
evcon_backend* bcknd = evcon_backend_init(static_backend_buf, sizeof(static_backend_buf), NULL, allocator, evcon_ev_free_loop, evcon_ev_fd_update, evcon_ev_timer_update, evcon_ev_async_update);
|
|
|
|
g_once_init_leave(&backend, bcknd);
|
|
}
|
|
|
|
return (evcon_backend*) backend;
|
|
}
|
|
|
|
evcon_loop* evcon_loop_from_ev(struct ev_loop *loop, evcon_allocator* allocator) {
|
|
evcon_backend *backend = evcon_ev_backend(allocator);
|
|
evcon_loop *evc_loop = evcon_loop_new(backend, allocator);
|
|
|
|
evcon_loop_set_backend_data(evc_loop, loop);
|
|
|
|
return evc_loop;
|
|
}
|