diff --git a/README.md b/README.md index b405da4..4911453 100644 --- a/README.md +++ b/README.md @@ -61,15 +61,16 @@ details, see [this article][4] at [lwn.net](http://lwn.net). API --- -Here is the interface to [libuEv]. It handles three different types of -events: I/O (files, sockets, message queues, etc.), timers, and signals. +The C interface to [libuEv] is very simple. It handles three different +types of events: I/O (files, sockets, message queues, etc.), timers, and +signals. With a slight caveat on signals ```C /* Callback example, arg is passed from watcher's *_init() * w->fd holds the file descriptor, events is set by libuEv * to indicate if any of UEV_READ and/or UEV_WRITE is ready. */ - void callback (uev_ctx_t *ctx, uev_t *w, void *arg, int events); + void callback (uev_t *w, void *arg, int events); /* Event loop functions, notice use of flags! */ int uev_init (uev_ctx_t *ctx); @@ -111,10 +112,10 @@ file descriptor to monitor, and an event callback function, by calling the event type's `_init()` function with the `uev_ctx_t` context. ```C - void cleanup_exit(uev_ctx_t *ctx, uev_t *w, void *arg, int events) + void cleanup_exit(uev_t *w, void *arg, int events) { /* Graceful exit, with optional cleanup ... */ - uev_exit(ctx); + uev_exit(w->ctx); } uev_t termw; @@ -186,7 +187,7 @@ struct js_event { uint8_t number; /* axis/button number */ } e; -static void joystick_cb(uev_ctx_t *ctx, uev_t *w, void *arg, int events) +static void joystick_cb(uev_t *w, void *arg, int events) { read (w->fd, &e, sizeof(e)); diff --git a/examples/joystick.c b/examples/joystick.c index ecd783d..8e3874e 100644 --- a/examples/joystick.c +++ b/examples/joystick.c @@ -40,7 +40,7 @@ struct js_event { uint8_t number; /* axis/button number */ } e; -static void joystick_cb(uev_ctx_t *UNUSED(ctx), uev_t *w, void *UNUSED(arg), int UNUSED(events)) +static void joystick_cb(uev_t *w, void *UNUSED(arg), int UNUSED(events)) { if (read (w->fd, &e, sizeof(e)) < 0) errx(errno, "Failed reading joystick event"); diff --git a/examples/signal.c b/examples/signal.c index 3e0306d..fa849ed 100644 --- a/examples/signal.c +++ b/examples/signal.c @@ -69,13 +69,13 @@ static int callback(arg_t *arg, int event, void *foo) return 42; } -static void sigsegv_cb(uev_ctx_t *UNUSED(ctx), uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) +static void sigsegv_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) { warnx("PID %d caused segfault.", getpid()); exit(-1); } -static void sigchld_cb(uev_ctx_t *UNUSED(ctx), uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) +static void sigchld_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) { pid_t pid = waitpid(-1, NULL, WNOHANG); @@ -83,7 +83,7 @@ static void sigchld_cb(uev_ctx_t *UNUSED(ctx), uev_t *UNUSED(w), void *UNUSED(ar warnx("PID %d exited, bye.", pid); } -static void work_cb(uev_ctx_t *UNUSED(ctx), uev_t *UNUSED(w), void *arg, int UNUSED(events)) +static void work_cb(uev_t *UNUSED(w), void *arg, int UNUSED(events)) { int status = 0; pid_t pid; @@ -102,15 +102,17 @@ static void work_cb(uev_ctx_t *UNUSED(ctx), uev_t *UNUSED(w), void *arg, int UNU if (WIFEXITED(status)) printf("Child exited normally => %d\n", WEXITSTATUS(status)); else if (WCOREDUMP(status)) - printf("Child crashed!\n"); + printf("Child crashed! %s\n", DO_SEGFAULT + ? "As expected, everything is OK." + : "This should not happen!"); else printf("Child did not exit normally!\n"); } -static void exit_cb(uev_ctx_t *ctx, uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) +static void exit_cb(uev_t *w, void *UNUSED(arg), int UNUSED(events)) { printf("Process deadline reached, exiting!\n"); - uev_exit(ctx); + uev_exit(w->ctx); } int main(void) @@ -120,6 +122,8 @@ int main(void) /* Initialize libuEv */ uev_init(&ctx); + + /* Setup callbacks */ uev_signal_init(&ctx, &sigsegv_watcher, sigsegv_cb, NULL, SIGSEGV); uev_signal_init(&ctx, &sigchld_watcher, sigchld_cb, NULL, SIGCHLD); uev_timer_init(&ctx, &timeout_watcher, work_cb, &arg, 400, 0); diff --git a/examples/test.c b/examples/test.c index 22c7c42..33456ae 100644 --- a/examples/test.c +++ b/examples/test.c @@ -40,33 +40,33 @@ static int in, out; static int period = 0; static uev_t *watchdog; -static void lifetime_cb(uev_ctx_t *ctx, uev_t UNUSED(*w), void *arg, int UNUSED(events)) +static void lifetime_cb(uev_t *w, void *arg, int UNUSED(events)) { fprintf(stderr, "\nLifetime exceeded, program completed successfully! (arg:%p)\n", arg); - uev_exit(ctx); + uev_exit(w->ctx); } /* The pipe watchdog, if it triggers we haven't received data in time. */ -static void timeout_cb(uev_ctx_t *ctx, uev_t *UNUSED(w), void *arg, int UNUSED(events)) +static void timeout_cb(uev_t *w, void *arg, int UNUSED(events)) { watchdog = NULL; fprintf(stderr, "\nTimeout exceeded %p\n", arg); // uev_timer_stop(w); <-- No need to stop timers with period=0 :) - uev_exit(ctx); + uev_exit(w->ctx); } -static void periodic_task(uev_ctx_t UNUSED(*ctx), uev_t UNUSED(*w), void UNUSED(*arg), int UNUSED(events)) +static void periodic_task(uev_t UNUSED(*w), void UNUSED(*arg), int UNUSED(events)) { fprintf(stderr, "|"); } -static void signal_cb(uev_ctx_t *UNUSED(ctx), uev_t *w, void *UNUSED(arg), int UNUSED(events)) +static void signal_cb(uev_t *w, void *UNUSED(arg), int UNUSED(events)) { fprintf(stderr, w->signo == SIGINT ? "^Cv" : "^\v"); } -static void pipe_read_cb(uev_ctx_t *UNUSED(ctx), uev_t UNUSED(*w), void UNUSED(*arg), int UNUSED(events)) +static void pipe_read_cb(uev_t UNUSED(*w), void UNUSED(*arg), int UNUSED(events)) { int cnt; char msg[50]; @@ -80,7 +80,7 @@ static void pipe_read_cb(uev_ctx_t *UNUSED(ctx), uev_t UNUSED(*w), void UNUSED(* fprintf(stderr, "%.*s.%d ", cnt, msg, cnt); } -static void pipe_write_cb(uev_ctx_t UNUSED(*ctx), uev_t *w, void *arg, int UNUSED(events)) +static void pipe_write_cb(uev_t *w, void *arg, int UNUSED(events)) { my_t *my = arg; char *msg = "TESTING"; diff --git a/uev.c b/uev.c index db72c9f..fa7c8e6 100644 --- a/uev.c +++ b/uev.c @@ -297,7 +297,7 @@ int uev_run(uev_ctx_t *ctx, int flags) } if (w->cb) - w->cb((struct uev *)ctx, w, w->arg); + w->cb(w, w->arg, events[i].events & UEV_EVENT_MASK); if (UEV_TIMER_TYPE == w->type) { if (!w->timeout) diff --git a/uev.h b/uev.h index f20fdb3..fd7b6fc 100644 --- a/uev.h +++ b/uev.h @@ -38,6 +38,7 @@ #define UEV_NONE 0 #define UEV_READ EPOLLIN #define UEV_WRITE EPOLLOUT +#define UEV_EVENT_MASK (UEV_READ | UEV_WRITE) /* Run flags */ #define UEV_ONCE 1 @@ -73,7 +74,7 @@ typedef struct uev { int events; /* Watcher callback with optional argument */ - void (*cb)(struct uev *, struct uev *, void *); + void (*cb)(struct uev *, void *, int); void *arg; /* Timer watchers, time in milliseconds */ @@ -85,7 +86,7 @@ typedef struct uev { } uev_t; /* Generic callback for watchers */ -typedef void (uev_cb_t)(uev_ctx_t *ctx, uev_t *w, void *arg, int events); +typedef void (uev_cb_t)(uev_t *w, void *arg, int events); /* Private methods, do not use directly! */ int uev_watcher_init (uev_ctx_t *ctx, uev_t *w, uev_type_t type, uev_cb_t *cb, void *arg, int fd, int events);