mirror of
https://github.com/troglobit/libuev.git
synced 2026-11-02 12:30:29 +00:00
Major refactor: API change, code cleanup, remove calloc()/free()
- Rename all _create() functions --> _init() - Rename all _delete() functions --> _stop() - Watchers are automatically started, except - Timer watchers are automatically started by uev_run() - Allow I/O watchers to watch either EV_READ/EV_WRITE or both events - Extend callbacks with a received events field - Remove calloc()/free(), let user handle this - Make event has-a context when initializing it => simplifies API - Internal uev_watcher_*() API mostly handles epoll stop/start Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
1 parent
c69ce87eb8
commit
d6e0146803
7 files changed
+362
-279
No files matched your search
@@ -34,7 +34,7 @@ CC = $(CROSS)gcc
|
|||||||
AR = $(CROSS)ar
|
AR = $(CROSS)ar
|
||||||
STRIP = $(CROSS)strip
|
STRIP = $(CROSS)strip
|
||||||
CFLAGS += -fPIC -Os
|
CFLAGS += -fPIC -Os
|
||||||
CPPFLAGS += -W -Wall -Iinclude
|
CPPFLAGS += -W -Wall -Werror -Iinclude
|
||||||
ARFLAGS = crus
|
ARFLAGS = crus
|
||||||
JUNK = *~ *.bak *.map .*.d DEADJOE *.gdb *.elf core core.*
|
JUNK = *~ *.bak *.map .*.d DEADJOE *.gdb *.elf core core.*
|
||||||
|
|
||||||
|
|||||||
@@ -29,28 +29,53 @@
|
|||||||
/**
|
/**
|
||||||
* Create an I/O watcher
|
* Create an I/O watcher
|
||||||
* @param ctx A valid libuev context
|
* @param ctx A valid libuev context
|
||||||
* @param handler I/O callback
|
* @param w Pointer to an uev_t watcher
|
||||||
* @param data Optional callback argument
|
* @param cb I/O callback
|
||||||
* @param fd File descriptor to watch
|
* @param arg Optional callback argument
|
||||||
* @param dir Direction of I/O to watch for: %UEV_DIR_INBOUND, or %UEV_DIR_OUTBOUND
|
* @param fd File descriptor to watch, or -1 to register an empty watcher
|
||||||
|
* @param events Requested events to watch for, a mask of %UEV_READ and %UEV_WRITE
|
||||||
*
|
*
|
||||||
* @return The new I/O watcher, or %NULL if invalid pointers or out or memory.
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
*/
|
*/
|
||||||
uev_t *uev_io_create(uev_ctx_t *ctx, uev_cb_t *handler, void *data, int fd, uev_dir_t dir)
|
int uev_io_init(uev_ctx_t *ctx, uev_t *w, uev_cb_t *cb, void *arg, int fd, int events)
|
||||||
{
|
{
|
||||||
return uev_watcher_create(ctx, UEV_FILE_TYPE, fd, dir, handler, data);
|
if (uev_watcher_init(ctx, w, UEV_IO_TYPE, cb, arg, fd, events))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (fd < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return uev_watcher_start(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an I/O watcher
|
* Reset an I/O watcher
|
||||||
* @param ctx A valid libuev context
|
* @param w Pointer to an uev_t watcher
|
||||||
* @param w I/O watcher
|
* @param fd New file descriptor to monitor
|
||||||
|
* @param events Requested events to watch for, a mask of %UEV_READ and %UEV_WRITE
|
||||||
*
|
*
|
||||||
* @return POSIX OK(0) or non-zero with @param errno set.
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
*/
|
*/
|
||||||
int uev_io_delete(uev_ctx_t *ctx, uev_t *w)
|
int uev_io_set(uev_t *w, int fd, int events)
|
||||||
{
|
{
|
||||||
return uev_watcher_delete(ctx, w);
|
if (uev_io_stop(w))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Remove from internal list */
|
||||||
|
LIST_REMOVE(w, link);
|
||||||
|
|
||||||
|
return uev_io_init(w->ctx, w, (uev_cb_t *)w->cb, w->arg, fd, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop an I/O watcher
|
||||||
|
* @param w Pointer to an uev_t watcher
|
||||||
|
*
|
||||||
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
|
*/
|
||||||
|
int uev_io_stop(uev_t *w)
|
||||||
|
{
|
||||||
|
return uev_watcher_stop(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h> /* calloc(), free() */
|
#include <string.h> /* memset() */
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#include <sys/signalfd.h> /* struct signalfd_siginfo */
|
#include <sys/signalfd.h> /* struct signalfd_siginfo */
|
||||||
#include <unistd.h> /* close(), read() */
|
#include <unistd.h> /* close(), read() */
|
||||||
@@ -32,103 +32,135 @@
|
|||||||
#include "uev.h"
|
#include "uev.h"
|
||||||
|
|
||||||
/* Private to libuev, do not use directly! */
|
/* Private to libuev, do not use directly! */
|
||||||
uev_t *uev_watcher_create(uev_ctx_t *ctx, uev_type_t type, int fd, uev_dir_t dir, uev_cb_t *cb, void *arg)
|
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)
|
||||||
{
|
|
||||||
uev_t *w;
|
|
||||||
struct epoll_event ev;
|
|
||||||
|
|
||||||
if (!ctx || !cb) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
w = (uev_t *)calloc(1, sizeof(*w));
|
|
||||||
if (!w)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
w->fd = fd;
|
|
||||||
w->type = type;
|
|
||||||
w->cb = (void *)cb;
|
|
||||||
w->arg = arg;
|
|
||||||
|
|
||||||
ev.events = dir == UEV_DIR_OUTBOUND ? EPOLLOUT : EPOLLIN;
|
|
||||||
ev.data.ptr = w;
|
|
||||||
if (epoll_ctl(ctx->efd, EPOLL_CTL_ADD, fd, &ev) < 0) {
|
|
||||||
free(w);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LIST_INSERT_HEAD(&ctx->watchers, w, link);
|
|
||||||
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Private to libuev, do not use directly! */
|
|
||||||
int uev_watcher_delete(uev_ctx_t *ctx, uev_t *w)
|
|
||||||
{
|
{
|
||||||
if (!ctx || !w) {
|
if (!ctx || !w) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove from kernel */
|
memset(w, 0, sizeof(*w));
|
||||||
epoll_ctl(ctx->efd, EPOLL_CTL_DEL, w->fd, NULL);
|
w->ctx = ctx;
|
||||||
|
w->fd = fd;
|
||||||
|
w->type = type;
|
||||||
|
w->cb = (void *)cb;
|
||||||
|
w->arg = arg;
|
||||||
|
w->events = events;
|
||||||
|
|
||||||
/* Remove from internal list */
|
LIST_INSERT_HEAD(&w->ctx->watchers, w, link);
|
||||||
LIST_REMOVE(w, link);
|
|
||||||
free(w);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Private to libuev, do not use directly! */
|
||||||
|
int uev_watcher_start(uev_t *w)
|
||||||
|
{
|
||||||
|
struct epoll_event ev;
|
||||||
|
|
||||||
|
if (!w || w->fd < 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w->active)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ev.events = w->events;
|
||||||
|
ev.data.ptr = w;
|
||||||
|
if (epoll_ctl(w->ctx->fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
w->active = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Private to libuev, do not use directly! */
|
||||||
|
int uev_watcher_stop(uev_t *w)
|
||||||
|
{
|
||||||
|
if (!w) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!w->active)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Remove from kernel */
|
||||||
|
epoll_ctl(w->ctx->fd, EPOLL_CTL_DEL, w->fd, NULL);
|
||||||
|
w->active = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an event loop context
|
* Create an event loop context
|
||||||
|
* @param ctx Pointer to an uev_ctx_t context to be initialized
|
||||||
*
|
*
|
||||||
* @return Returns a new uev_ctx_t context, or %NULL on error.
|
* @return POSIX OK(0) on success, or non-zero on error.
|
||||||
*/
|
*/
|
||||||
uev_ctx_t *uev_ctx_create(void)
|
int uev_init(uev_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
uev_ctx_t *ctx;
|
|
||||||
|
|
||||||
fd = epoll_create(1);
|
fd = epoll_create(1);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
ctx = (uev_ctx_t *)calloc(1, sizeof(*ctx));
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
if (!ctx) {
|
ctx->fd = fd;
|
||||||
close(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->efd = fd;
|
|
||||||
LIST_INIT(&ctx->watchers);
|
LIST_INIT(&ctx->watchers);
|
||||||
|
|
||||||
return ctx;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy an event loop context
|
* Terminate the event loop
|
||||||
* @param ctx A valid libuev context
|
* @param ctx A valid libuev context
|
||||||
|
*
|
||||||
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
*/
|
*/
|
||||||
void uev_ctx_delete(uev_ctx_t *ctx)
|
int uev_exit(uev_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
|
if (!ctx) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
while (!LIST_EMPTY(&ctx->watchers)) {
|
while (!LIST_EMPTY(&ctx->watchers)) {
|
||||||
uev_t *w = LIST_FIRST(&ctx->watchers);
|
uev_t *w = LIST_FIRST(&ctx->watchers);
|
||||||
|
|
||||||
if (UEV_TIMER_TYPE == w->type)
|
/* Remove from internal list */
|
||||||
uev_timer_delete(ctx, w);
|
LIST_REMOVE(w, link);
|
||||||
else
|
|
||||||
uev_io_delete(ctx, w);
|
if (!w->active)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (w->type) {
|
||||||
|
case UEV_TIMER_TYPE:
|
||||||
|
uev_timer_stop(w);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UEV_SIGNAL_TYPE:
|
||||||
|
uev_signal_stop(w);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UEV_IO_TYPE:
|
||||||
|
uev_io_stop(w);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close(ctx->efd);
|
ctx->running = 0;
|
||||||
free(ctx);
|
close(ctx->fd);
|
||||||
|
ctx->fd = -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the event loop
|
* Start the event loop
|
||||||
* @param ctx A valid libuev context
|
* @param ctx A valid libuev context
|
||||||
*
|
*
|
||||||
* @return POSIX OK(0) upon successful termination of the event loop, or non-zero on error.
|
* @return POSIX OK(0) upon successful termination of the event loop, or non-zero on error.
|
||||||
*/
|
*/
|
||||||
@@ -137,7 +169,7 @@ int uev_run(uev_ctx_t *ctx)
|
|||||||
int result = 0;
|
int result = 0;
|
||||||
uev_t *w;
|
uev_t *w;
|
||||||
|
|
||||||
if (!ctx) {
|
if (!ctx || ctx->fd < 0) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -148,14 +180,17 @@ int uev_run(uev_ctx_t *ctx)
|
|||||||
/* Start all dormant timers */
|
/* Start all dormant timers */
|
||||||
LIST_FOREACH(w, &ctx->watchers, link) {
|
LIST_FOREACH(w, &ctx->watchers, link) {
|
||||||
if (UEV_TIMER_TYPE == w->type)
|
if (UEV_TIMER_TYPE == w->type)
|
||||||
uev_timer_set(ctx, w, w->timeout, w->period);
|
uev_timer_set(w, w->timeout, w->period);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ctx->running) {
|
while (ctx->running) {
|
||||||
int i, nfds;
|
int i, nfds;
|
||||||
struct epoll_event events[UEV_MAX_EVENTS];
|
struct epoll_event events[UEV_MAX_EVENTS];
|
||||||
|
|
||||||
while ((nfds = epoll_wait(ctx->efd, events, UEV_MAX_EVENTS, -1)) < 0) {
|
while ((nfds = epoll_wait(ctx->fd, events, UEV_MAX_EVENTS, -1)) < 0) {
|
||||||
|
if (!ctx->running)
|
||||||
|
break;
|
||||||
|
|
||||||
if (EINTR == errno)
|
if (EINTR == errno)
|
||||||
continue; /* Signalled, try again */
|
continue; /* Signalled, try again */
|
||||||
exit:
|
exit:
|
||||||
@@ -164,7 +199,7 @@ int uev_run(uev_ctx_t *ctx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < nfds; i++) {
|
for (i = 0; ctx->running && i < nfds; i++) {
|
||||||
w = (uev_t *)events[i].data.ptr;
|
w = (uev_t *)events[i].data.ptr;
|
||||||
|
|
||||||
if (UEV_TIMER_TYPE == w->type) {
|
if (UEV_TIMER_TYPE == w->type) {
|
||||||
@@ -172,6 +207,9 @@ int uev_run(uev_ctx_t *ctx)
|
|||||||
|
|
||||||
if (read(w->fd, &exp, sizeof(exp)) != sizeof(exp))
|
if (read(w->fd, &exp, sizeof(exp)) != sizeof(exp))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
if (!w->period)
|
||||||
|
w->timeout = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UEV_SIGNAL_TYPE == w->type) {
|
if (UEV_SIGNAL_TYPE == w->type) {
|
||||||
@@ -188,8 +226,8 @@ int uev_run(uev_ctx_t *ctx)
|
|||||||
w->cb((struct uev *)ctx, w, w->arg);
|
w->cb((struct uev *)ctx, w, w->arg);
|
||||||
|
|
||||||
if (UEV_TIMER_TYPE == w->type) {
|
if (UEV_TIMER_TYPE == w->type) {
|
||||||
if (!w->period)
|
if (!w->timeout)
|
||||||
uev_timer_delete(ctx, w);
|
uev_timer_stop(w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,15 +235,6 @@ int uev_run(uev_ctx_t *ctx)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Terminate the event loop
|
|
||||||
* @param ctx A valid libuev context
|
|
||||||
*/
|
|
||||||
void uev_exit(uev_ctx_t *ctx)
|
|
||||||
{
|
|
||||||
ctx->running = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* version-control: t
|
* version-control: t
|
||||||
|
|||||||
@@ -33,90 +33,90 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a signal watcher
|
* Create a signal watcher
|
||||||
* @param ctx A valid libuev context
|
* @param ctx A valid libuev context
|
||||||
* @param handler Timer callback
|
* @param w Pointer to an uev_t watcher
|
||||||
* @param data Optional callback argument
|
* @param cb Timer callback
|
||||||
* @param signo Signal to watch for
|
* @param arg Optional callback argument
|
||||||
|
* @param signo Signal to watch for
|
||||||
*
|
*
|
||||||
* @return The new watcher, or %NULL with @param errno set on error.
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
*/
|
*/
|
||||||
uev_t *uev_signal_create(uev_ctx_t *ctx, uev_cb_t *handler, void *data, int signo)
|
int uev_signal_init(uev_ctx_t *ctx, uev_t *w, uev_cb_t *cb, void *arg, int signo)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
uev_t *w;
|
|
||||||
|
|
||||||
sigemptyset(&mask);
|
sigemptyset(&mask);
|
||||||
fd = signalfd(-1, &mask, SFD_NONBLOCK);
|
fd = signalfd(-1, &mask, SFD_NONBLOCK);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
w = uev_watcher_create(ctx, UEV_SIGNAL_TYPE, fd, UEV_DIR_INBOUND, handler, data);
|
if (uev_watcher_init(ctx, w, UEV_SIGNAL_TYPE, cb, arg, fd, UEV_READ))
|
||||||
if (!w)
|
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if (uev_signal_set(ctx, w, signo)) {
|
if (uev_signal_set(w, signo)) {
|
||||||
uev_watcher_delete(ctx, w);
|
uev_watcher_stop(w);
|
||||||
exit:
|
exit:
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return w;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset a signal watcher
|
* Reset a signal watcher
|
||||||
* @param ctx A valid libuev context
|
* @param w Watcher to reset
|
||||||
* @param w Watcher to reset
|
* @param signo New signal to watch for
|
||||||
* @param signo New signal to watch for
|
|
||||||
*
|
*
|
||||||
* @return POSIX OK(0) or non-zero with @param errno set.
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
*/
|
*/
|
||||||
int uev_signal_set(uev_ctx_t *ctx, uev_t *w, int signo)
|
int uev_signal_set(uev_t *w, int signo)
|
||||||
{
|
{
|
||||||
sigset_t mask;
|
sigset_t mask;
|
||||||
|
|
||||||
if (!ctx || !w) {
|
/* Every watcher must be registered to a context */
|
||||||
|
if (!w || !w->ctx) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle stopped signal watchers */
|
||||||
|
if (w->fd < 0) {
|
||||||
|
/* Remove from internal list */
|
||||||
|
LIST_REMOVE(w, link);
|
||||||
|
|
||||||
|
if (uev_signal_init(w->ctx, w, (uev_cb_t *)w->cb, w->arg, signo))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
sigemptyset(&mask);
|
sigemptyset(&mask);
|
||||||
sigaddset(&mask, signo);
|
sigaddset(&mask, signo);
|
||||||
|
|
||||||
/* Block signals so that they aren't handled
|
/* Block signals so that they aren't handled
|
||||||
according to their default dispositions */
|
according to their default dispositions */
|
||||||
|
|
||||||
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
|
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (signalfd(w->fd, &mask, SFD_NONBLOCK) < 0)
|
if (signalfd(w->fd, &mask, SFD_NONBLOCK) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return uev_watcher_start(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a signal watcher
|
* Stop a signal watcher
|
||||||
* @param ctx A valid libuev context
|
* @param w Watcher to stop
|
||||||
* @param w Watcher to delete
|
|
||||||
*
|
*
|
||||||
* @return POSIX OK(0) or non-zero with @param errno set.
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
*/
|
*/
|
||||||
int uev_signal_delete(uev_ctx_t *ctx, uev_t *w)
|
int uev_signal_stop(uev_t *w)
|
||||||
{
|
{
|
||||||
int fd;
|
if (uev_watcher_stop(w))
|
||||||
|
|
||||||
if (!ctx || !w) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
uev_timer_set(ctx, w, 0, 0);
|
close(w->fd);
|
||||||
fd = w->fd;
|
w->fd = -1;
|
||||||
uev_watcher_delete(ctx, w);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,105 +30,113 @@
|
|||||||
|
|
||||||
#include "uev.h"
|
#include "uev.h"
|
||||||
|
|
||||||
|
#define UNUSED(arg) arg __attribute__ ((unused))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int counter;
|
||||||
|
} my_t;
|
||||||
|
|
||||||
static int in, out;
|
static int in, out;
|
||||||
static int period = 0;
|
static int period = 0;
|
||||||
static uev_t *timer = NULL;
|
static uev_t *watchdog;
|
||||||
|
|
||||||
static void lifetime_cb(uev_ctx_t *ctx, uev_t *w __attribute__ ((unused)), void *data)
|
static void lifetime_cb(uev_ctx_t *ctx, uev_t UNUSED(*w), void *arg, int UNUSED(events))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\nLifetime exceeded %p\n", data);
|
fprintf(stderr, "\nLifetime exceeded %p\n", arg);
|
||||||
uev_exit(ctx);
|
uev_exit(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The pipe watchdog, if it triggers we haven't received data in time. */
|
/* The pipe watchdog, if it triggers we haven't received data in time. */
|
||||||
static void timeout_cb(uev_ctx_t *ctx, uev_t *w, void *data)
|
static void timeout_cb(uev_ctx_t *ctx, uev_t *w, void *arg, int UNUSED(events))
|
||||||
{
|
{
|
||||||
timer = NULL;
|
watchdog = NULL;
|
||||||
fprintf(stderr, "\nTimeout exceeded %p\n", data);
|
fprintf(stderr, "\nTimeout exceeded %p\n", arg);
|
||||||
|
|
||||||
uev_timer_delete(ctx, w);
|
uev_timer_stop(w);
|
||||||
uev_exit(ctx);
|
uev_exit(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void periodic_task(uev_ctx_t *ctx __attribute__ ((unused)), uev_t *w __attribute__ ((unused)), void *data __attribute__ ((unused)))
|
static void periodic_task(uev_ctx_t UNUSED(*ctx), uev_t UNUSED(*w), void UNUSED(*arg), int UNUSED(events))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "|");
|
fprintf(stderr, "|");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void signal_cb(uev_ctx_t *ctx __attribute__ ((unused)), uev_t *w, void *data __attribute__ ((unused)))
|
static void signal_cb(uev_ctx_t *UNUSED(ctx), uev_t *w, void *UNUSED(arg), int UNUSED(events))
|
||||||
{
|
{
|
||||||
fprintf(stderr, w->signo == SIGINT ? "^Cv" : "^\v");
|
fprintf(stderr, w->signo == SIGINT ? "^Cv" : "^\v");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pipe_read_cb(uev_ctx_t *ctx, uev_t *w __attribute__ ((unused)), void *data __attribute__ ((unused)))
|
static void pipe_read_cb(uev_ctx_t *UNUSED(ctx), uev_t UNUSED(*w), void UNUSED(*arg), int UNUSED(events))
|
||||||
{
|
{
|
||||||
int cnt;
|
int cnt;
|
||||||
char msg[50];
|
char msg[50];
|
||||||
|
|
||||||
/* Kick watchdog */
|
/* Kick watchdog */
|
||||||
if (timer)
|
if (watchdog)
|
||||||
uev_timer_set(ctx, timer, 1000, 0);
|
uev_timer_set(watchdog, 1000, 0);
|
||||||
|
|
||||||
cnt = read(in, msg, sizeof(msg));
|
cnt = read(in, msg, sizeof(msg));
|
||||||
// fprintf(stderr, "READ %.*s %d\n", cnt, msg, cnt);
|
// fprintf(stderr, "READ %.*s %d\n", cnt, msg, cnt);
|
||||||
fprintf(stderr, "%.*s.%d ", cnt, msg, cnt);
|
fprintf(stderr, "%.*s.%d ", cnt, msg, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pipe_write_cb(uev_ctx_t *ctx, uev_t *w __attribute__ ((unused)), void *data)
|
static void pipe_write_cb(uev_ctx_t UNUSED(*ctx), uev_t *w, void *arg, int UNUSED(events))
|
||||||
{
|
{
|
||||||
int cnt = (int)(intptr_t)data;
|
my_t *my = arg;
|
||||||
char *msg = "TESTING";
|
char *msg = "TESTING";
|
||||||
|
|
||||||
if (write(out, msg, cnt) < 0) {
|
if (write(out, msg, my->counter) < 0) {
|
||||||
perror("\nFailed writing to pipe");
|
perror("\nFailed writing to pipe");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fprintf(stderr, "WRITE %.*s %d\n", cnt, msg, cnt);
|
// fprintf(stderr, "WRITE %.*s %d\n", my->counter, msg, my->counter);
|
||||||
fprintf(stderr, "%d ", cnt);
|
fprintf(stderr, "%d ", my->counter);
|
||||||
period = cnt + 5;
|
period = my->counter + 5;
|
||||||
|
my->counter++;
|
||||||
|
|
||||||
uev_timer_create(ctx, pipe_write_cb, (void *)(intptr_t)(cnt + 1), period * 100, 0);
|
uev_timer_set(w, period * 100, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int fd[2];
|
int fd[2];
|
||||||
uev_ctx_t *ctx = uev_ctx_create();
|
my_t my = { .counter = 1 };
|
||||||
|
uev_t timeout, wdt, periodic, writer, reader, sigint_watcher, sigquit_watcher;
|
||||||
/* Total program execution time */
|
uev_ctx_t ctx;
|
||||||
uev_timer_create(ctx, lifetime_cb, (void *)(intptr_t)2, 4000, 0);
|
|
||||||
|
|
||||||
/* Work load, one timer callback writes to a pipe periodically,
|
/* Work load, one timer callback writes to a pipe periodically,
|
||||||
* and one I/O watcher that is called every time the pipe has
|
* and one I/O watcher that is called every time the pipe has
|
||||||
* some data. */
|
* some data. */
|
||||||
if (pipe(fd) < 0) {
|
if (pipe(fd) < 0)
|
||||||
/* Cleanup */
|
|
||||||
uev_ctx_delete(ctx);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
|
/* */
|
||||||
|
uev_init(&ctx);
|
||||||
|
|
||||||
|
/* Signal watchers, Ctrl-C => SIGINT, Ctrl-\ => SIGQUIT */
|
||||||
|
uev_signal_init(&ctx, &sigint_watcher, signal_cb, NULL, SIGINT);
|
||||||
|
uev_signal_init(&ctx, &sigquit_watcher, signal_cb, NULL, SIGQUIT);
|
||||||
|
|
||||||
|
/* Total program execution time */
|
||||||
|
uev_timer_init(&ctx, &timeout, lifetime_cb, (void *)(intptr_t)2, 4000, 0);
|
||||||
|
|
||||||
|
/* Main pipe worker and consumer */
|
||||||
in = fd[0];
|
in = fd[0];
|
||||||
out = fd[1];
|
out = fd[1];
|
||||||
uev_timer_create(ctx, pipe_write_cb, (void *)(intptr_t)1, 400, 0);
|
uev_io_init(&ctx, &reader, pipe_read_cb, NULL, in, UEV_READ);
|
||||||
uev_io_create(ctx, pipe_read_cb, NULL, in, UEV_DIR_INBOUND);
|
uev_timer_init(&ctx, &writer, pipe_write_cb, &my, 400, 0);
|
||||||
|
|
||||||
/* Watchdog for the above timer callback, if it doesn't wake up
|
/* Watchdog for the above timer callback, if it doesn't wake up
|
||||||
* and write to the pipe within a given deadline it will bark. */
|
* and write to the pipe within a given deadline it will bark. */
|
||||||
timer = uev_timer_create(ctx, timeout_cb, (void *)(intptr_t)1, 950, 0);
|
uev_timer_init(&ctx, &wdt, timeout_cb, (void *)(intptr_t)1, 950, 0);
|
||||||
|
watchdog = &wdt;
|
||||||
|
|
||||||
/* Periodic background task */
|
/* Periodic background task */
|
||||||
uev_timer_create(ctx, periodic_task, NULL, 200, 200);
|
uev_timer_init(&ctx, &periodic, periodic_task, NULL, 200, 200);
|
||||||
|
|
||||||
/* Signal watchers, Ctrl-C => SIGINT, Ctrl-\ => SIGQUIT */
|
|
||||||
uev_signal_create(ctx, signal_cb, NULL, SIGINT);
|
|
||||||
uev_signal_create(ctx, signal_cb, NULL, SIGQUIT);
|
|
||||||
|
|
||||||
/* Start event loop */
|
/* Start event loop */
|
||||||
uev_run(ctx);
|
uev_run(&ctx);
|
||||||
|
|
||||||
/* Tear down event context */
|
|
||||||
uev_ctx_delete(ctx);
|
|
||||||
|
|
||||||
fprintf(stderr, "Period is %d must be 10: %s\n", period, 10 == period ? "OK" : "ERROR!");
|
fprintf(stderr, "Period is %d must be 10: %s\n", period, 10 == period ? "OK" : "ERROR!");
|
||||||
if (10 != period)
|
if (10 != period)
|
||||||
|
|||||||
@@ -30,107 +30,123 @@
|
|||||||
#include "uev.h"
|
#include "uev.h"
|
||||||
|
|
||||||
|
|
||||||
static struct timespec msec2tspec(int msec)
|
static void msec2tspec(int msec, struct timespec *ts)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
if (msec) {
|
||||||
|
ts->tv_sec = msec / 1000;
|
||||||
ts.tv_sec = msec / 1000;
|
ts->tv_nsec = (msec % 1000) * 1000000;
|
||||||
ts.tv_nsec = (msec % 1000) * 1000000;
|
} else {
|
||||||
|
ts->tv_sec = 0;
|
||||||
return ts;
|
ts->tv_nsec = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a timer watcher
|
* Create and start a timer watcher
|
||||||
* @param ctx A valid libuev context
|
* @param ctx A valid libuev context
|
||||||
* @param handler Timer callback
|
* @param w Pointer to an uev_t watcher
|
||||||
* @param data Optional callback argument
|
* @param cb Callback function
|
||||||
* @param timeout Timeout in milliseconds before @param handler is called
|
* @param arg Optional callback argument
|
||||||
* @param period For periodic timers this is the period time that @param timeout is reset to
|
* @param timeout Timeout in milliseconds before @param cb is called
|
||||||
|
* @param period For periodic timers this is the period time that @param timeout is reset to
|
||||||
*
|
*
|
||||||
* For one-shot timers you set @param period to zero and only use @param
|
* For one-shot timers you set @param period to zero and only use @param
|
||||||
* timeout. For periodic timers you likely set @param timeout to either
|
* timeout. For periodic timers you likely set @param timeout to either
|
||||||
* zero, to call it as soon as the event loop starts, or to the same
|
* zero, to call it as soon as the event loop starts, or to the same
|
||||||
* value as @param period. When the timer expires, the @param handler
|
* value as @param period. When the timer expires, the @param cb
|
||||||
* is called, with the optional @param data argument. A non-periodic
|
* is called, with the optional @param arg argument. A non-periodic
|
||||||
* timer ends its life there, while a periodic task's @param timeout is
|
* timer ends its life there, while a periodic task's @param timeout is
|
||||||
* reset to the @param period and restarted.
|
* reset to the @param period and restarted.
|
||||||
*
|
*
|
||||||
* @return The new watcher, or %NULL with @param errno set on error.
|
* A timer is automatically started if the event loop is already
|
||||||
*/
|
* running, otherwise it is kept on hold until triggered by calling
|
||||||
uev_t *uev_timer_create(uev_ctx_t *ctx, uev_cb_t *handler, void *data, int timeout, int period)
|
* uev_run().
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
uev_t *w;
|
|
||||||
|
|
||||||
fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
|
||||||
if (fd < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
w = uev_watcher_create(ctx, UEV_TIMER_TYPE, fd, UEV_DIR_INBOUND, handler, data);
|
|
||||||
if (!w)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
if (uev_timer_set(ctx, w, timeout, period)) {
|
|
||||||
uev_watcher_delete(ctx, w);
|
|
||||||
exit:
|
|
||||||
close(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset or reschedule a timer
|
|
||||||
* @param ctx A valid libuev context
|
|
||||||
* @param w Watcher to reset
|
|
||||||
* @param timeout Timeout in milliseconds before @param handler is called
|
|
||||||
* @param period For periodic timers this is the period time that @param timeout is reset to
|
|
||||||
*
|
*
|
||||||
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
*/
|
*/
|
||||||
int uev_timer_set(uev_ctx_t *ctx, uev_t *w, int timeout, int period)
|
int uev_timer_init(uev_ctx_t *ctx, uev_t *w, uev_cb_t *cb, void *arg, int timeout, int period)
|
||||||
{
|
{
|
||||||
struct itimerspec time;
|
int fd;
|
||||||
|
|
||||||
if (!ctx || !w) {
|
fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (uev_watcher_init(ctx, w, UEV_TIMER_TYPE, cb, arg, fd, UEV_READ))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (uev_timer_set(w, timeout, period)) {
|
||||||
|
uev_watcher_stop(w);
|
||||||
|
exit:
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset a timer
|
||||||
|
* @param w Watcher to reset
|
||||||
|
* @param timeout Timeout in milliseconds before @param cb is called
|
||||||
|
* @param period For periodic timers this is the period time that @param timeout is reset to
|
||||||
|
*
|
||||||
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
|
*/
|
||||||
|
int uev_timer_set(uev_t *w, int timeout, int period)
|
||||||
|
{
|
||||||
|
/* Every watcher must be registered to a context */
|
||||||
|
if (!w || !w->ctx) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle stopped timers */
|
||||||
|
if (w->fd < 0) {
|
||||||
|
/* Timer already stopped */
|
||||||
|
if (!timeout && !period)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Remove from internal list */
|
||||||
|
LIST_REMOVE(w, link);
|
||||||
|
|
||||||
|
if (uev_timer_init(w->ctx, w, (uev_cb_t *)w->cb, w->arg, timeout, period))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
w->timeout = timeout;
|
w->timeout = timeout;
|
||||||
w->period = period;
|
w->period = period;
|
||||||
|
|
||||||
if (!ctx->running)
|
if (w->ctx->running) {
|
||||||
return 0;
|
struct itimerspec time;
|
||||||
|
|
||||||
time.it_value = msec2tspec(timeout);
|
msec2tspec(timeout, &time.it_value);
|
||||||
time.it_interval = msec2tspec(period);
|
msec2tspec(period, &time.it_interval);
|
||||||
|
timerfd_settime(w->fd, 0, &time, NULL);
|
||||||
|
|
||||||
return timerfd_settime(w->fd, 0, &time, NULL);
|
return uev_watcher_start(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a timer watcher
|
* Stop and unregister a timer watcher
|
||||||
* @param ctx A valid libuev context
|
* @param w Watcher to stop
|
||||||
* @param w Watcher to delete
|
|
||||||
*
|
*
|
||||||
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
* @return POSIX OK(0) or non-zero with @param errno set on error.
|
||||||
*/
|
*/
|
||||||
int uev_timer_delete(uev_ctx_t *ctx, uev_t *w)
|
int uev_timer_stop(uev_t *w)
|
||||||
{
|
{
|
||||||
int fd;
|
if (uev_watcher_stop(w))
|
||||||
|
|
||||||
if (!ctx || !w) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
uev_timer_set(ctx, w, 0, 0);
|
/* Stop kernel timer */
|
||||||
fd = w->fd;
|
uev_timer_set(w, 0, 0);
|
||||||
uev_watcher_delete(ctx, w);
|
|
||||||
close(fd);
|
/* Close timerfd, will have to be reopened again on reset */
|
||||||
|
close(w->fd);
|
||||||
|
w->fd = -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,78 +26,83 @@
|
|||||||
#ifndef LIBUEV_UEV_H_
|
#ifndef LIBUEV_UEV_H_
|
||||||
#define LIBUEV_UEV_H_
|
#define LIBUEV_UEV_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
|
|
||||||
/* Max. number of simulateneous events */
|
/* Max. number of simulateneous events */
|
||||||
#define UEV_MAX_EVENTS 10
|
#define UEV_MAX_EVENTS 10
|
||||||
|
|
||||||
/* Forward declare due to dependencys, don't try this at home. */
|
/* I/O events, for signals and timers revents will always be UEV_READ */
|
||||||
struct uev;
|
#define UEV_NONE 0
|
||||||
|
#define UEV_READ EPOLLIN
|
||||||
|
#define UEV_WRITE EPOLLOUT
|
||||||
|
|
||||||
/* I/O direction */
|
/* I/O, timer, or signal watcher */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UEV_DIR_INBOUND = 0,
|
UEV_IO_TYPE = 1,
|
||||||
UEV_DIR_OUTBOUND = 1
|
|
||||||
} uev_dir_t;
|
|
||||||
|
|
||||||
/* I/O, timer, or signal */
|
|
||||||
typedef enum {
|
|
||||||
UEV_FILE_TYPE = 1,
|
|
||||||
UEV_TIMER_TYPE,
|
UEV_TIMER_TYPE,
|
||||||
UEV_SIGNAL_TYPE,
|
UEV_SIGNAL_TYPE,
|
||||||
} uev_type_t;
|
} uev_type_t;
|
||||||
|
|
||||||
/* I/O event watcher */
|
/* Forward declare due to dependencys, don't try this at home kids. */
|
||||||
typedef struct uev {
|
struct uev;
|
||||||
LIST_ENTRY(uev) link; /* For queue.h linked list */
|
|
||||||
|
|
||||||
/* Common to all watchers */
|
|
||||||
uev_type_t type;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
/* Watcher callback with optional argument */
|
|
||||||
void (*cb)(struct uev *, struct uev *, void *);
|
|
||||||
void *arg;
|
|
||||||
|
|
||||||
/* Timer watchers, time in milliseconds */
|
|
||||||
int timeout;
|
|
||||||
int period;
|
|
||||||
|
|
||||||
/* Signal watchers */
|
|
||||||
int signo;
|
|
||||||
} uev_t;
|
|
||||||
|
|
||||||
/* Main libuev context type */
|
/* Main libuev context type */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int running;
|
int running;
|
||||||
int efd; /* For epoll() */
|
int fd; /* For epoll() */
|
||||||
LIST_HEAD(, uev) watchers;
|
LIST_HEAD(,uev) watchers;
|
||||||
} uev_ctx_t;
|
} uev_ctx_t;
|
||||||
|
|
||||||
|
/* I/O event watcher */
|
||||||
|
typedef struct uev {
|
||||||
|
LIST_ENTRY(uev) link; /* For queue.h linked list */
|
||||||
|
|
||||||
|
/* Common to all watchers */
|
||||||
|
uev_ctx_t *ctx;
|
||||||
|
uev_type_t type;
|
||||||
|
int active;
|
||||||
|
int fd;
|
||||||
|
int events;
|
||||||
|
|
||||||
|
/* Watcher callback with optional argument */
|
||||||
|
void (*cb)(struct uev *, struct uev *, void *);
|
||||||
|
void *arg;
|
||||||
|
|
||||||
|
/* Timer watchers, time in milliseconds */
|
||||||
|
int timeout;
|
||||||
|
int period;
|
||||||
|
|
||||||
|
/* Signal watchers */
|
||||||
|
int signo;
|
||||||
|
} uev_t;
|
||||||
|
|
||||||
/* Generic callback for watchers */
|
/* Generic callback for watchers */
|
||||||
typedef void (uev_cb_t) (uev_ctx_t *ctx, uev_t *w, void *data);
|
typedef void (uev_cb_t)(uev_ctx_t *ctx, uev_t *w, void *arg, int events);
|
||||||
|
|
||||||
/* Private methods, do not use directly! */
|
/* Private methods, do not use directly! */
|
||||||
uev_t *uev_watcher_create(uev_ctx_t *ctx, uev_type_t type, int fd, uev_dir_t dir, uev_cb_t *cb, void *data);
|
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);
|
||||||
int uev_watcher_delete(uev_ctx_t *ctx, uev_t *w);
|
int uev_watcher_start (uev_t *w);
|
||||||
|
int uev_watcher_stop (uev_t *w);
|
||||||
|
|
||||||
/* Public interface */
|
/* Public interface */
|
||||||
uev_t *uev_io_create (uev_ctx_t *ctx, uev_cb_t *cb, void *data, int fd, uev_dir_t dir);
|
int uev_init (uev_ctx_t *ctx);
|
||||||
int uev_io_delete (uev_ctx_t *ctx, uev_t *w);
|
int uev_exit (uev_ctx_t *ctx);
|
||||||
|
|
||||||
int uev_timer_set (uev_ctx_t *ctx, uev_t *w, int timeout, int period);
|
int uev_run (uev_ctx_t *ctx);
|
||||||
uev_t *uev_timer_create (uev_ctx_t *ctx, uev_cb_t *cb, void *data, int timeout, int period);
|
|
||||||
int uev_timer_delete (uev_ctx_t *ctx, uev_t *w);
|
|
||||||
|
|
||||||
uev_t *uev_signal_create (uev_ctx_t *ctx, uev_cb_t *handler, void *data, int signo);
|
int uev_io_init (uev_ctx_t *ctx, uev_t *w, uev_cb_t *cb, void *arg, int fd, int events);
|
||||||
int uev_signal_set (uev_ctx_t *ctx, uev_t *w, int signo);
|
int uev_io_set (uev_t *w, int fd, int events);
|
||||||
int uev_signal_delete (uev_ctx_t *ctx, uev_t *w);
|
int uev_io_stop (uev_t *w);
|
||||||
|
|
||||||
uev_ctx_t *uev_ctx_create (void);
|
int uev_timer_init (uev_ctx_t *ctx, uev_t *w, uev_cb_t *cb, void *arg, int timeout, int period);
|
||||||
void uev_ctx_delete (uev_ctx_t *uev);
|
int uev_timer_set (uev_t *w, int timeout, int period);
|
||||||
|
int uev_timer_stop (uev_t *w);
|
||||||
|
|
||||||
int uev_run (uev_ctx_t *ctx);
|
int uev_signal_init (uev_ctx_t *ctx, uev_t *w, uev_cb_t *cb, void *arg, int signo);
|
||||||
void uev_exit (uev_ctx_t *ctx);
|
int uev_signal_set (uev_t *w, int signo);
|
||||||
|
int uev_signal_stop (uev_t *w);
|
||||||
|
|
||||||
#endif /* LIBUEV_UEV_H_ */
|
#endif /* LIBUEV_UEV_H_ */
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user