From 940e61846e97ba62153d5b977b0823f196607743 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Mar 2009 14:15:07 +0100 Subject: tevent: add tevent_common_loop_wait() helper function and use it tevent_loop_wait should do the same for all backends. It should loop as long as we have pending events. metze --- lib/tevent/tevent.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'lib/tevent/tevent.c') diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 867cfc08fe..31dc58d98e 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -511,6 +511,34 @@ done: return ret; } +/* + return on failure or (with 0) if all fd events are removed +*/ +int tevent_common_loop_wait(struct tevent_context *ev, + const char *location) +{ + /* + * loop as long as we have events pending + */ + while (ev->fd_events || + ev->timer_events || + ev->immediate_events || + ev->signal_events) { + int ret; + ret = _tevent_loop_once(ev, location); + if (ret != 0) { + tevent_debug(ev, TEVENT_DEBUG_FATAL, + "_tevent_loop_once() failed: %d - %s\n", + ret, strerror(errno)); + return ret; + } + } + + tevent_debug(ev, TEVENT_DEBUG_WARNING, + "tevent_common_loop_wait() out of events\n"); + return 0; +} + /* return on failure or (with 0) if all fd events are removed */ -- cgit From 66886f8966dff8a980a5b9d2daa3fbb20fe5ca8e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 13 Mar 2009 15:47:33 +0100 Subject: tevent: add support for immediate events They're like directly triggered timed events, but you can preallocated them and scheduling them will not fail. metze --- lib/tevent/tevent.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'lib/tevent/tevent.c') diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 31dc58d98e..ba2d93f4b9 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -143,6 +143,7 @@ int tevent_common_context_destructor(struct tevent_context *ev) { struct tevent_fd *fd, *fn; struct tevent_timer *te, *tn; + struct tevent_immediate *ie, *in; struct tevent_signal *se, *sn; if (ev->pipe_fde) { @@ -162,6 +163,13 @@ int tevent_common_context_destructor(struct tevent_context *ev) DLIST_REMOVE(ev->timer_events, te); } + for (ie = ev->immediate_events; ie; ie = in) { + in = ie->next; + ie->event_ctx = NULL; + ie->cancel_fn = NULL; + DLIST_REMOVE(ev->immediate_events, ie); + } + for (se = ev->signal_events; se; se = sn) { sn = se->next; se->event_ctx = NULL; @@ -349,6 +357,47 @@ struct tevent_timer *_tevent_add_timer(struct tevent_context *ev, handler_name, location); } +/* + allocate an immediate event + return NULL on failure (memory allocation error) +*/ +struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx, + const char *location) +{ + struct tevent_immediate *im; + + im = talloc(mem_ctx, struct tevent_immediate); + if (im == NULL) return NULL; + + im->prev = NULL; + im->next = NULL; + im->event_ctx = NULL; + im->create_location = location; + im->handler = NULL; + im->private_data = NULL; + im->handler_name = NULL; + im->schedule_location = NULL; + im->cancel_fn = NULL; + im->additional_data = NULL; + + return im; +} + +/* + schedule an immediate event + return NULL on failure +*/ +void _tevent_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ev, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ + ev->ops->schedule_immediate(im, ev, handler, private_data, + handler_name, location); +} + /* add a signal event -- cgit From 13b6663e23a424473d14324ac229a21e1e90580a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 19 Mar 2009 11:21:36 +1100 Subject: fixed a logic bug in the tevent nesting code The event nesting code never triggered as nesting.level was never greater than 1. The main event loop needs to increase the nesting level by 1. I also added a paranoia check to the nesting setup call. The API as currently written cannot support multiple nesting hooks, so we need to abort if multiple hooks are tried. --- lib/tevent/tevent.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'lib/tevent/tevent.c') diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index ba2d93f4b9..56fd6aec7a 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -427,6 +427,14 @@ void tevent_loop_set_nesting_hook(struct tevent_context *ev, tevent_nesting_hook hook, void *private_data) { + if (ev->nesting.hook_fn && + (ev->nesting.hook_fn != hook || + ev->nesting.hook_private != private_data)) { + /* the way the nesting hook code is currently written + we cannot support two different nesting hooks at the + same time. */ + tevent_abort(ev, "tevent: Violation of nesting hook rules\n"); + } ev->nesting.hook_fn = hook; ev->nesting.hook_private = private_data; } @@ -593,5 +601,9 @@ int tevent_common_loop_wait(struct tevent_context *ev, */ int _tevent_loop_wait(struct tevent_context *ev, const char *location) { - return ev->ops->loop_wait(ev, location); + int ret; + ev->nesting.level++; + ret = ev->ops->loop_wait(ev, location); + ev->nesting.level--; + return ret; } -- cgit From 36e7045340bbc7d6567008bdd87c4cdf717835bd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 19 Mar 2009 14:31:43 +0100 Subject: tevent: fix the nesting logic Only tevent_loop_once and tevent_loop_until() should care about the nesting level. This fixes the samba3 printing code where we use tevent_loop_wait() and don't allow nested events. We still call the nesting hook for all levels, we need to decide if we really want this... metze --- lib/tevent/tevent.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'lib/tevent/tevent.c') diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 56fd6aec7a..0c02e46f3c 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -468,6 +468,8 @@ int _tevent_loop_once(struct tevent_context *ev, const char *location) errno = ELOOP; return -1; } + } + if (ev->nesting.level > 0) { if (ev->nesting.hook_fn) { int ret2; ret2 = ev->nesting.hook_fn(ev, @@ -485,7 +487,7 @@ int _tevent_loop_once(struct tevent_context *ev, const char *location) ret = ev->ops->loop_once(ev, location); - if (ev->nesting.level > 1) { + if (ev->nesting.level > 0) { if (ev->nesting.hook_fn) { int ret2; ret2 = ev->nesting.hook_fn(ev, @@ -525,6 +527,8 @@ int _tevent_loop_until(struct tevent_context *ev, errno = ELOOP; return -1; } + } + if (ev->nesting.level > 0) { if (ev->nesting.hook_fn) { int ret2; ret2 = ev->nesting.hook_fn(ev, @@ -547,7 +551,7 @@ int _tevent_loop_until(struct tevent_context *ev, } } - if (ev->nesting.level > 1) { + if (ev->nesting.level > 0) { if (ev->nesting.hook_fn) { int ret2; ret2 = ev->nesting.hook_fn(ev, @@ -601,9 +605,5 @@ int tevent_common_loop_wait(struct tevent_context *ev, */ int _tevent_loop_wait(struct tevent_context *ev, const char *location) { - int ret; - ev->nesting.level++; - ret = ev->ops->loop_wait(ev, location); - ev->nesting.level--; - return ret; + return ev->ops->loop_wait(ev, location); } -- cgit