summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2009-03-13 15:47:33 +0100
committerStefan Metzmacher <metze@samba.org>2009-03-17 19:59:00 +0100
commit66886f8966dff8a980a5b9d2daa3fbb20fe5ca8e (patch)
tree383df98ac1fc50173ea09e0496eff2040185aeec
parentd27be1d5fa3fdcaac07b527ad14b0d10ef27c0bb (diff)
downloadsamba-66886f8966dff8a980a5b9d2daa3fbb20fe5ca8e.tar.gz
samba-66886f8966dff8a980a5b9d2daa3fbb20fe5ca8e.tar.bz2
samba-66886f8966dff8a980a5b9d2daa3fbb20fe5ca8e.zip
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
-rw-r--r--lib/tevent/libtevent.m43
-rw-r--r--lib/tevent/tevent.c49
-rw-r--r--lib/tevent/tevent.h19
-rw-r--r--lib/tevent/tevent_epoll.c28
-rw-r--r--lib/tevent/tevent_immediate.c139
-rw-r--r--lib/tevent/tevent_internal.h35
-rw-r--r--lib/tevent/tevent_select.c28
-rw-r--r--lib/tevent/tevent_standard.c28
8 files changed, 295 insertions, 34 deletions
diff --git a/lib/tevent/libtevent.m4 b/lib/tevent/libtevent.m4
index c316823a71..20730b17d6 100644
--- a/lib/tevent/libtevent.m4
+++ b/lib/tevent/libtevent.m4
@@ -26,7 +26,8 @@ AC_SUBST(TEVENT_LIBS)
TEVENT_CFLAGS="-I$teventdir"
-TEVENT_OBJ="tevent.o tevent_fd.o tevent_timed.o tevent_signal.o tevent_debug.o tevent_util.o"
+TEVENT_OBJ="tevent.o tevent_debug.o tevent_util.o"
+TEVENT_OBJ="$TEVENT_OBJ tevent_fd.o tevent_timed.o tevent_immediate.o tevent_signal.o"
TEVENT_OBJ="$TEVENT_OBJ tevent_req.o tevent_wakeup.o tevent_queue.o"
TEVENT_OBJ="$TEVENT_OBJ tevent_standard.o tevent_select.o"
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;
@@ -350,6 +358,47 @@ struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
}
/*
+ 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
sa_flags are flags to sigaction(2)
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index 4a3f51ae5e..6e64a8cdd9 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -37,6 +37,7 @@ struct tevent_context;
struct tevent_ops;
struct tevent_fd;
struct tevent_timer;
+struct tevent_immediate;
struct tevent_signal;
/* event handler types */
@@ -52,6 +53,9 @@ typedef void (*tevent_timer_handler_t)(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval current_time,
void *private_data);
+typedef void (*tevent_immediate_handler_t)(struct tevent_context *ctx,
+ struct tevent_immediate *im,
+ void *private_data);
typedef void (*tevent_signal_handler_t)(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
@@ -87,6 +91,21 @@ struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
_tevent_add_timer(ev, mem_ctx, next_event, handler, private_data, \
#handler, __location__)
+struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
+ const char *location);
+#define tevent_create_immediate(mem_ctx) \
+ _tevent_create_immediate(mem_ctx, __location__)
+
+void _tevent_schedule_immediate(struct tevent_immediate *im,
+ struct tevent_context *ctx,
+ tevent_immediate_handler_t handler,
+ void *private_data,
+ const char *handler_name,
+ const char *location);
+#define tevent_schedule_immediate(im, ctx, handler, private_data) \
+ _tevent_schedule_immediate(im, ctx, handler, private_data, \
+ #handler, __location__);
+
struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
int signum,
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 32544593de..7c7f389d5b 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -404,8 +404,13 @@ static int epoll_event_loop_once(struct tevent_context *ev, const char *location
struct epoll_event_context);
struct timeval tval;
- if (epoll_ev->ev->signal_events &&
- tevent_common_check_signal(epoll_ev->ev)) {
+ if (ev->signal_events &&
+ tevent_common_check_signal(ev)) {
+ return 0;
+ }
+
+ if (ev->immediate_events &&
+ tevent_common_loop_immediate(ev)) {
return 0;
}
@@ -420,15 +425,16 @@ static int epoll_event_loop_once(struct tevent_context *ev, const char *location
}
static const struct tevent_ops epoll_event_ops = {
- .context_init = epoll_event_context_init,
- .add_fd = epoll_event_add_fd,
- .set_fd_close_fn= tevent_common_fd_set_close_fn,
- .get_fd_flags = tevent_common_fd_get_flags,
- .set_fd_flags = epoll_event_set_fd_flags,
- .add_timer = tevent_common_add_timer,
- .add_signal = tevent_common_add_signal,
- .loop_once = epoll_event_loop_once,
- .loop_wait = tevent_common_loop_wait,
+ .context_init = epoll_event_context_init,
+ .add_fd = epoll_event_add_fd,
+ .set_fd_close_fn = tevent_common_fd_set_close_fn,
+ .get_fd_flags = tevent_common_fd_get_flags,
+ .set_fd_flags = epoll_event_set_fd_flags,
+ .add_timer = tevent_common_add_timer,
+ .schedule_immediate = tevent_common_schedule_immediate,
+ .add_signal = tevent_common_add_signal,
+ .loop_once = epoll_event_loop_once,
+ .loop_wait = tevent_common_loop_wait,
};
bool tevent_epoll_init(void)
diff --git a/lib/tevent/tevent_immediate.c b/lib/tevent/tevent_immediate.c
new file mode 100644
index 0000000000..1ac293e175
--- /dev/null
+++ b/lib/tevent/tevent_immediate.c
@@ -0,0 +1,139 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ common events code for immediate events
+
+ Copyright (C) Stefan Metzmacher 2009
+
+ ** NOTE! The following LGPL license applies to the tevent
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "tevent.h"
+#include "tevent_internal.h"
+#include "tevent_util.h"
+
+static void tevent_common_immediate_cancel(struct tevent_immediate *im)
+{
+ if (!im->event_ctx) {
+ return;
+ }
+
+ tevent_debug(im->event_ctx, TEVENT_DEBUG_TRACE,
+ "Cancel immediate event %p \"%s\"\n",
+ im, im->handler_name);
+
+ /* let the backend free im->additional_data */
+ if (im->cancel_fn) {
+ im->cancel_fn(im);
+ }
+
+ DLIST_REMOVE(im->event_ctx->immediate_events, im);
+ im->event_ctx = NULL;
+ im->handler = NULL;
+ im->private_data = NULL;
+ im->handler_name = NULL;
+ im->schedule_location = NULL;
+ im->cancel_fn = NULL;
+ im->additional_data = NULL;
+
+ talloc_set_destructor(im, NULL);
+}
+
+/*
+ destroy an immediate event
+*/
+static int tevent_common_immediate_destructor(struct tevent_immediate *im)
+{
+ tevent_common_immediate_cancel(im);
+ return 0;
+}
+
+/*
+ * schedule an immediate event on
+ */
+void tevent_common_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)
+{
+ tevent_common_immediate_cancel(im);
+
+ if (!handler) {
+ return;
+ }
+
+ im->event_ctx = ev;
+ im->handler = handler;
+ im->private_data = private_data;
+ im->handler_name = handler_name;
+ im->schedule_location = location;
+ im->cancel_fn = NULL;
+ im->additional_data = NULL;
+
+ DLIST_ADD_END(ev->immediate_events, im, struct tevent_immediate *);
+ talloc_set_destructor(im, tevent_common_immediate_destructor);
+
+ tevent_debug(ev, TEVENT_DEBUG_TRACE,
+ "Schedule immediate event \"%s\": %p\n",
+ handler_name, im);
+}
+
+/*
+ trigger the first immediate event and return true
+ if no event was triggered return false
+*/
+bool tevent_common_loop_immediate(struct tevent_context *ev)
+{
+ struct tevent_immediate *im = ev->immediate_events;
+ tevent_immediate_handler_t handler;
+ void *private_data;
+
+ if (!im) {
+ return false;
+ }
+
+ tevent_debug(ev, TEVENT_DEBUG_TRACE,
+ "Run immediate event \"%s\": %p\n",
+ im->handler_name, im);
+
+ /*
+ * remember the handler and then clear the event
+ * the handler might reschedule the event
+ */
+ handler = im->handler;
+ private_data = im->private_data;
+
+ DLIST_REMOVE(im->event_ctx->immediate_events, im);
+ im->event_ctx = NULL;
+ im->handler = NULL;
+ im->private_data = NULL;
+ im->handler_name = NULL;
+ im->schedule_location = NULL;
+ im->cancel_fn = NULL;
+ im->additional_data = NULL;
+
+ talloc_set_destructor(im, NULL);
+
+ handler(ev, im, private_data);
+
+ return true;
+}
+
diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h
index f63a58aadd..cf54242da1 100644
--- a/lib/tevent/tevent_internal.h
+++ b/lib/tevent/tevent_internal.h
@@ -143,6 +143,15 @@ struct tevent_ops {
void *private_data,
const char *handler_name,
const char *location);
+
+ /* immediate event functions */
+ void (*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);
+
/* signal functions */
struct tevent_signal *(*add_signal)(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
@@ -188,6 +197,21 @@ struct tevent_timer {
void *additional_data;
};
+struct tevent_immediate {
+ struct tevent_immediate *prev, *next;
+ struct tevent_context *event_ctx;
+ tevent_immediate_handler_t handler;
+ /* this is private for the specific handler */
+ void *private_data;
+ /* this is for debugging only! */
+ const char *handler_name;
+ const char *create_location;
+ const char *schedule_location;
+ /* this is private for the events_ops implementation */
+ void (*cancel_fn)(struct tevent_immediate *im);
+ void *additional_data;
+};
+
struct tevent_signal {
struct tevent_signal *prev, *next;
struct tevent_context *event_ctx;
@@ -222,6 +246,9 @@ struct tevent_context {
/* list of timed events - used by common code */
struct tevent_timer *timer_events;
+ /* list of immediate events - used by common code */
+ struct tevent_immediate *immediate_events;
+
/* list of signal events - used by common code */
struct tevent_signal *signal_events;
@@ -273,6 +300,14 @@ struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev,
const char *location);
struct timeval tevent_common_loop_timer_delay(struct tevent_context *);
+void tevent_common_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);
+bool tevent_common_loop_immediate(struct tevent_context *ev);
+
struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
int signum,
diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c
index 1c295d7ca4..d97418991a 100644
--- a/lib/tevent/tevent_select.c
+++ b/lib/tevent/tevent_select.c
@@ -210,8 +210,13 @@ static int select_event_loop_once(struct tevent_context *ev, const char *locatio
struct select_event_context);
struct timeval tval;
- if (select_ev->ev->signal_events &&
- tevent_common_check_signal(select_ev->ev)) {
+ if (ev->signal_events &&
+ tevent_common_check_signal(ev)) {
+ return 0;
+ }
+
+ if (ev->immediate_events &&
+ tevent_common_loop_immediate(ev)) {
return 0;
}
@@ -224,15 +229,16 @@ static int select_event_loop_once(struct tevent_context *ev, const char *locatio
}
static const struct tevent_ops select_event_ops = {
- .context_init = select_event_context_init,
- .add_fd = select_event_add_fd,
- .set_fd_close_fn= tevent_common_fd_set_close_fn,
- .get_fd_flags = tevent_common_fd_get_flags,
- .set_fd_flags = tevent_common_fd_set_flags,
- .add_timer = tevent_common_add_timer,
- .add_signal = tevent_common_add_signal,
- .loop_once = select_event_loop_once,
- .loop_wait = tevent_common_loop_wait,
+ .context_init = select_event_context_init,
+ .add_fd = select_event_add_fd,
+ .set_fd_close_fn = tevent_common_fd_set_close_fn,
+ .get_fd_flags = tevent_common_fd_get_flags,
+ .set_fd_flags = tevent_common_fd_set_flags,
+ .add_timer = tevent_common_add_timer,
+ .schedule_immediate = tevent_common_schedule_immediate,
+ .add_signal = tevent_common_add_signal,
+ .loop_once = select_event_loop_once,
+ .loop_wait = tevent_common_loop_wait,
};
bool tevent_select_init(void)
diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c
index 88db6a1725..c3f8b36e84 100644
--- a/lib/tevent/tevent_standard.c
+++ b/lib/tevent/tevent_standard.c
@@ -524,8 +524,13 @@ static int std_event_loop_once(struct tevent_context *ev, const char *location)
struct std_event_context);
struct timeval tval;
- if (std_ev->ev->signal_events &&
- tevent_common_check_signal(std_ev->ev)) {
+ if (ev->signal_events &&
+ tevent_common_check_signal(ev)) {
+ return 0;
+ }
+
+ if (ev->immediate_events &&
+ tevent_common_loop_immediate(ev)) {
return 0;
}
@@ -544,15 +549,16 @@ static int std_event_loop_once(struct tevent_context *ev, const char *location)
}
static const struct tevent_ops std_event_ops = {
- .context_init = std_event_context_init,
- .add_fd = std_event_add_fd,
- .set_fd_close_fn= tevent_common_fd_set_close_fn,
- .get_fd_flags = tevent_common_fd_get_flags,
- .set_fd_flags = std_event_set_fd_flags,
- .add_timer = tevent_common_add_timer,
- .add_signal = tevent_common_add_signal,
- .loop_once = std_event_loop_once,
- .loop_wait = tevent_common_loop_wait,
+ .context_init = std_event_context_init,
+ .add_fd = std_event_add_fd,
+ .set_fd_close_fn = tevent_common_fd_set_close_fn,
+ .get_fd_flags = tevent_common_fd_get_flags,
+ .set_fd_flags = std_event_set_fd_flags,
+ .add_timer = tevent_common_add_timer,
+ .schedule_immediate = tevent_common_schedule_immediate,
+ .add_signal = tevent_common_add_signal,
+ .loop_once = std_event_loop_once,
+ .loop_wait = tevent_common_loop_wait,
};