Simplify linked list of I/O watchers and its garbage collect mechanism.

Simplifed uev_io_t by removing uev_io_rem_t completely.  A refactor that
would not have been possible without the BSD queue.h API.  This makes
the code readable and thus maintainable and less error prone.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson committed 2013-07-21 08:31:33 +02:00
1 parent ece4e31c52
commit e1b1daf5e3
2 files changed
+20 -28

No files matched your search

+17 -18
View File
@@ -46,7 +46,6 @@ uev_io_t *uev_io_create(uev_t *ctx, int fd, uev_dir_t dir, uev_io_cb_t handler,
if (!w)
return NULL;
w->rem.ent = w;
w->fd = fd;
w->dir = dir;
w->handler = (void *)handler;
@@ -60,22 +59,23 @@ uev_io_t *uev_io_create(uev_t *ctx, int fd, uev_dir_t dir, uev_io_cb_t handler,
int uev_io_delete(uev_t *ctx, uev_io_t *w)
{
uev_io_rem_t *ent;
uev_io_t *tmp;
if (!ctx || !w) {
errno = EINVAL;
return -1;
}
TAILQ_FOREACH(ent, &ctx->io_delist, link) {
if (ent->ent == w) {
/* Check if already removed */
TAILQ_FOREACH(tmp, &ctx->io_delist, gc) {
if (tmp == w) {
errno = EALREADY;
return -1; /* Already removed */
return -1;
}
}
w->handler = NULL;
TAILQ_INSERT_TAIL(&ctx->io_delist, &w->rem, link);
TAILQ_INSERT_TAIL(&ctx->io_delist, w, gc);
return 0;
}
@@ -150,10 +150,11 @@ int uev_timer_delete(uev_t *ctx, uev_timer_t *w)
return -1;
}
/* Check if already removed */
TAILQ_FOREACH(tmp, &ctx->timer_delist, link) {
if (tmp == w) {
errno = EALREADY;
return -1; /* Already removed */
return -1;
}
}
@@ -191,7 +192,7 @@ static int do_run_pending(uev_t *ctx, int immediate)
diff = TIME_DIFF_MSEC(now, ctx->base_time);
}
/* Reap timer zombies */
/* Garbage collect */
TAILQ_FOREACH_SAFE(timer, &ctx->timer_delist, link, tmp) {
TAILQ_REMOVE(&ctx->timer_delist, timer, link);
free(timer);
@@ -248,13 +249,12 @@ static int do_run_pending(uev_t *ctx, int immediate)
}
}
/* Garbage collect */
if (!TAILQ_EMPTY(&ctx->io_delist)) {
uev_io_rem_t *tmp;
TAILQ_FOREACH(tmp, &ctx->io_delist, link) {
TAILQ_REMOVE(&ctx->io_delist, tmp, link);
TAILQ_REMOVE(&ctx->io_list, tmp->ent, link);
free(tmp->ent);
TAILQ_FOREACH(w, &ctx->io_delist, gc) {
TAILQ_REMOVE(&ctx->io_delist, w, gc);
TAILQ_REMOVE(&ctx->io_list, w, link);
free(w);
}
}
} else if (diff > 0) {
@@ -286,10 +286,9 @@ void uev_run(uev_t *ctx)
/**
* Drive the timeouts ourself (from now on until an increment of -1)
* This is intended for use in testing frameworks
* Caveat emptor: Currently, interactions with the scheduler (agent) API is undefined.
* Not for use in uevs that use the agent scheduler
* @param ctx UEVlication context object
* @param msec Ms to advance. Use -1 to return to realtime
*
* @param ctx libuev context object
* @param msec Milliseconds to advance the timer. Use -1 to return to realtime
*/
void uev_run_tick(uev_t *ctx, int msec)
{
+3 -10
View File
@@ -33,10 +33,8 @@
( (now - then) / clock_tick * 1000 + \
((now - then) % clock_tick) * 1000 / clock_tick )
/* Forward declarations due to dependencys, don't try this at home. */
/* Forward declare due to dependencys, don't try this at home. */
struct uev;
struct uev_io;
struct uev_timer;
/* I/O direction */
typedef enum {
@@ -45,14 +43,9 @@ typedef enum {
} uev_dir_t;
/* I/O event watcher */
typedef struct uev_io_rem {
TAILQ_ENTRY(uev_io_rem) link;
struct uev_io *ent;
} uev_io_rem_t;
typedef struct uev_io {
TAILQ_ENTRY(uev_io) link;
uev_io_rem_t rem; ///< For postponed removal
TAILQ_ENTRY(uev_io) gc;
int fd; ///< File descriptor
uev_dir_t dir; ///< Direction: in or out
@@ -77,7 +70,7 @@ typedef struct {
TAILQ_HEAD(, uev_io) io_list; ///< File handlers
TAILQ_HEAD(, uev_timer) timer_list; ///< Timer handlers
TAILQ_HEAD(, uev_io_rem) io_delist; ///< List of file handles to be garbage collected
TAILQ_HEAD(, uev_io) io_delist; ///< List of file handles to be garbage collected
TAILQ_HEAD(, uev_timer) timer_delist; ///< List of timer handles to be garbage collected
clock_t base_time; ///< Time at last timer tick