summaryrefslogtreecommitdiff
path: root/source4/lib/events.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-01-23 11:49:15 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:09:08 -0500
commitfd62df64188c0f992876c72fdda8a6da5dba3090 (patch)
treea5f212e796816c648a3a0e49caa457eb597e292b /source4/lib/events.c
parent54eff1435dd69d489ae35834f17989f79011418e (diff)
downloadsamba-fd62df64188c0f992876c72fdda8a6da5dba3090.tar.gz
samba-fd62df64188c0f992876c72fdda8a6da5dba3090.tar.bz2
samba-fd62df64188c0f992876c72fdda8a6da5dba3090.zip
r4943: Smplified the events handling code a lot. The first source of
complexity was that events didn't automatically cleanup themselves. This was because the events code was written before we had talloc destructors, so you needed to call event_remove_XX() to clean the event out of the event lists from every piece of code that used events. I have now added automatic event destructors, which in turn allowed me to simplify a lot of the calling code. The 2nd source of complexity was caused by the ref_count, which was needed to cope with event handlers destroying events while handling them, which meant the linked lists became invalid, so the ref_count ws used to mark events for later destruction. The new system is much simpler. I now have a ev->destruction_count, which is incremented in all event destructors. The event dispatch code checks for changes to this and handles it. (This used to be commit a3c7417cfeab429ffb22d5546b205818f531a7b4)
Diffstat (limited to 'source4/lib/events.c')
-rw-r--r--source4/lib/events.c170
1 files changed, 85 insertions, 85 deletions
diff --git a/source4/lib/events.c b/source4/lib/events.c
index 54ec4ef927..6f0bdb4fdd 100644
--- a/source4/lib/events.c
+++ b/source4/lib/events.c
@@ -104,8 +104,7 @@ static void calc_maxfd(struct event_context *ev)
struct fd_event *e;
ev->maxfd = 0;
for (e=ev->fd_events; e; e=e->next) {
- if (e->ref_count &&
- e->fd > ev->maxfd) {
+ if (e->fd > ev->maxfd) {
ev->maxfd = e->fd;
}
}
@@ -117,7 +116,8 @@ static void calc_maxfd(struct event_context *ev)
this is used by modules that need to call on the events of a lower module
*/
-struct event_context *event_context_merge(struct event_context *ev, struct event_context *ev2)
+struct event_context *event_context_merge(struct event_context *ev,
+ struct event_context *ev2)
{
DLIST_CONCATENATE(ev->fd_events, ev2->fd_events, struct fd_event *);
DLIST_CONCATENATE(ev->timed_events, ev2->timed_events, struct timed_event *);
@@ -136,29 +136,42 @@ struct event_context *event_context_merge(struct event_context *ev, struct event
return ev;
}
+/* to mark the ev->maxfd invalid
+ * this means we need to recalculate it
+ */
+#define EVENT_INVALID_MAXFD (-1)
+
+
+static int event_fd_destructor(void *ptr)
+{
+ struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
+ if (fde->event_ctx->maxfd == fde->fd) {
+ fde->event_ctx->maxfd = EVENT_INVALID_MAXFD;
+ }
+ DLIST_REMOVE(fde->event_ctx->fd_events, fde);
+ fde->event_ctx->destruction_count++;
+ return 0;
+}
/*
add a fd based event
return NULL on failure (memory allocation error)
*/
-struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e)
+struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0)
{
- e = talloc_memdup(ev->events, e, sizeof(*e));
+ struct fd_event *e = talloc(ev->events, struct fd_event);
if (!e) return NULL;
+ *e = *e0;
DLIST_ADD(ev->fd_events, e);
- e->ref_count = 1;
+ e->event_ctx = ev;
if (e->fd > ev->maxfd) {
ev->maxfd = e->fd;
}
+ talloc_set_destructor(e, event_fd_destructor);
return e;
}
-/* to mark the ev->maxfd invalid
- * this means we need to recalculate it
- */
-#define EVENT_INVALID_MAXFD (-1)
-
/*
remove a fd based event
the event to remove is matched by looking at the handler
@@ -167,16 +180,8 @@ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e)
*/
BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1)
{
- struct fd_event *e;
- for (e=ev->fd_events; e; e=e->next) {
- if (e->ref_count &&
- e->fd == e1->fd &&
- e->handler == e1->handler) {
- e->ref_count--;
- return True;
- }
- }
- return False;
+ talloc_free(e1);
+ return True;
}
/*
@@ -184,10 +189,13 @@ BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1)
*/
void event_remove_fd_all(struct event_context *ev, int fd)
{
- struct fd_event *e;
- for (e=ev->fd_events; e; e=e->next) {
- if (e->ref_count && e->fd == fd) {
- e->ref_count--;
+ struct fd_event *e = ev->fd_events;
+ /* be careful to cope with extra reference counts on events */
+ while (e) {
+ if (talloc_free(ev->fd_events) == 0) {
+ e = ev->fd_events;
+ } else {
+ e = e->next;
}
}
}
@@ -197,26 +205,35 @@ void event_remove_fd_all(struct event_context *ev, int fd)
*/
void event_remove_fd_all_handler(struct event_context *ev, void *handler)
{
- struct fd_event *e;
- for (e=ev->fd_events; e; e=e->next) {
- if (e->ref_count &&
- handler == (void *)e->handler) {
- e->ref_count--;
+ struct fd_event *e, *next;
+ for (e=ev->fd_events; e; e=next) {
+ next = e->next;
+ if (handler == (void *)e->handler) {
+ talloc_free(e);
}
}
}
+static int event_timed_destructor(void *ptr)
+{
+ struct timed_event *te = talloc_get_type(ptr, struct timed_event);
+ DLIST_REMOVE(te->event_ctx->timed_events, te);
+ te->event_ctx->destruction_count++;
+ return 0;
+}
/*
add a timed event
return NULL on failure (memory allocation error)
*/
-struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e)
+struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e0)
{
- e = talloc_memdup(ev->events, e, sizeof(*e));
+ struct timed_event *e = talloc(ev->events, struct timed_event);
if (!e) return NULL;
- e->ref_count = 1;
+ *e = *e0;
+ e->event_ctx = ev;
DLIST_ADD(ev->timed_events, e);
+ talloc_set_destructor(e, event_timed_destructor);
return e;
}
@@ -224,28 +241,32 @@ struct timed_event *event_add_timed(struct event_context *ev, struct timed_event
remove a timed event
return False on failure (event not found)
*/
-BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1)
+BOOL event_remove_timed(struct event_context *ev, struct timed_event *e)
{
- struct timed_event *e;
- for (e=ev->timed_events; e; e=e->next) {
- if (e->ref_count && e == e1) {
- e->ref_count--;
- return True;
- }
- }
- return False;
+ talloc_free(e);
+ return True;
+}
+
+static int event_loop_destructor(void *ptr)
+{
+ struct loop_event *le = talloc_get_type(ptr, struct loop_event);
+ DLIST_REMOVE(le->event_ctx->loop_events, le);
+ le->event_ctx->destruction_count++;
+ return 0;
}
/*
add a loop event
return NULL on failure (memory allocation error)
*/
-struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e)
+struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e0)
{
- e = talloc_memdup(ev->events, e, sizeof(*e));
+ struct loop_event *e = talloc(ev->events, struct loop_event);
if (!e) return NULL;
- e->ref_count = 1;
+ *e = *e0;
+ e->event_ctx = ev;
DLIST_ADD(ev->loop_events, e);
+ talloc_set_destructor(e, event_loop_destructor);
return e;
}
@@ -254,17 +275,10 @@ struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e
the event to remove is matched only on the handler function
return False on failure (memory allocation error)
*/
-BOOL event_remove_loop(struct event_context *ev, struct loop_event *e1)
+BOOL event_remove_loop(struct event_context *ev, struct loop_event *e)
{
- struct loop_event *e;
- for (e=ev->loop_events; e; e=e->next) {
- if (e->ref_count &&
- e->handler == e1->handler) {
- e->ref_count--;
- return True;
- }
- }
- return False;
+ talloc_free(e);
+ return True;
}
@@ -288,6 +302,7 @@ int event_loop_once(struct event_context *ev)
struct timed_event *te;
int selrtn;
struct timeval tval, t;
+ uint32_t destruction_count = ev->destruction_count;
t = timeval_current();
@@ -295,14 +310,8 @@ int event_loop_once(struct event_context *ev)
event to remove itself */
for (le=ev->loop_events;le;) {
struct loop_event *next = le->next;
- if (le->ref_count == 0) {
- DLIST_REMOVE(ev->loop_events, le);
- talloc_free(le);
- } else {
- le->ref_count++;
- le->handler(ev, le, t);
- le->ref_count--;
- }
+ le->handler(ev, le, t);
+ if (destruction_count != ev->destruction_count) break;
le = next;
}
@@ -312,19 +321,11 @@ int event_loop_once(struct event_context *ev)
/* setup any fd events */
for (fe=ev->fd_events; fe; ) {
struct fd_event *next = fe->next;
- if (fe->ref_count == 0) {
- DLIST_REMOVE(ev->fd_events, fe);
- if (ev->maxfd == fe->fd) {
- ev->maxfd = EVENT_INVALID_MAXFD;
- }
- talloc_free(fe);
- } else {
- if (fe->flags & EVENT_FD_READ) {
- FD_SET(fe->fd, &r_fds);
- }
- if (fe->flags & EVENT_FD_WRITE) {
- FD_SET(fe->fd, &w_fds);
- }
+ if (fe->flags & EVENT_FD_READ) {
+ FD_SET(fe->fd, &r_fds);
+ }
+ if (fe->flags & EVENT_FD_WRITE) {
+ FD_SET(fe->fd, &w_fds);
}
fe = next;
}
@@ -379,10 +380,11 @@ int event_loop_once(struct event_context *ev)
uint16_t flags = 0;
if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ;
if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE;
- if (fe->ref_count && flags) {
- fe->ref_count++;
+ if (flags) {
fe->handler(ev, fe, t, flags);
- fe->ref_count--;
+ if (destruction_count != ev->destruction_count) {
+ break;
+ }
}
}
}
@@ -391,13 +393,11 @@ int event_loop_once(struct event_context *ev)
/* call any timed events that are now due */
for (te=ev->timed_events;te;) {
struct timed_event *next = te->next;
- if (te->ref_count == 0) {
- DLIST_REMOVE(ev->timed_events, te);
- talloc_free(te);
- } else if (timeval_compare(&te->next_event, &t) >= 0) {
- te->ref_count++;
+ if (timeval_compare(&te->next_event, &t) >= 0) {
te->handler(ev, te, t);
- te->ref_count--;
+ if (destruction_count != ev->destruction_count) {
+ break;
+ }
if (timeval_compare(&te->next_event, &t) >= 0) {
/* the handler didn't set a time for the
next event - remove the event */