diff options
Diffstat (limited to 'source4/lib/events.c')
-rw-r--r-- | source4/lib/events.c | 185 |
1 files changed, 93 insertions, 92 deletions
diff --git a/source4/lib/events.c b/source4/lib/events.c index ebfa164885..b2e0404e34 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -26,7 +26,7 @@ register one of the possible event types and implement that event somewhere else. - There are 4 types of event handling that are handled in this module: + There are 2 types of event handling that are handled in this module: 1) a file descriptor becoming readable or writeable. This is mostly used for network sockets, but can be used for any type of file @@ -41,15 +41,6 @@ like. When they are called the handler can choose to set the time for the next event. If next_event is not set then the event is removed. - 3) an event that happens every time through the select loop. These - sorts of events should be very fast, as they will occur a - lot. Mostly used for things like destroying a talloc context or - checking a signal flag. - - 4) an event triggered by a signal. These can be one shot or - repeated. You can have more than one handler registered for a - single signal if you want to. - To setup a set of events you first need to create a event_context structure using the function event_context_init(); This returns a 'struct event_context' that you use in all subsequent calls. @@ -59,8 +50,7 @@ Finally, you call event_loop_wait() to block waiting for one of the events to occor. In normal operation event_loop_wait() will loop - forever, unless you call event_loop_exit() from inside one of your - handler functions. + forever. */ @@ -70,6 +60,46 @@ #include "dlinklist.h" #include "events.h" + +/* + please read the comments in events.c before modifying +*/ + + +struct event_context { + /* list of filedescriptor events */ + struct fd_event { + struct event_context *event_ctx; + struct fd_event *next, *prev; + int fd; + uint16_t flags; /* see EVENT_FD_* flags */ + event_fd_handler_t handler; + void *private; + } *fd_events; + + /* list of timed events */ + struct timed_event { + struct event_context *event_ctx; + struct timed_event *next, *prev; + struct timeval next_event; + event_timed_handler_t handler; + void *private; + } *timed_events; + + /* the maximum file descriptor number in fd_events */ + int maxfd; + + /* information for exiting from the event loop */ + int exit_code; + + /* this is changed by the destructors for any event type. It + is used to detect event destruction by event handlers, + which means the code that is calling all event handles + needs to assume that the linked list is no longer valid + */ + uint32_t destruction_count; +}; + /* create a event_context structure. This must be the first events call, and all subsequent calls pass this event_context as the first @@ -82,21 +112,10 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx) ev = talloc_zero(mem_ctx, struct event_context); if (!ev) return NULL; - ev->events = talloc_new(ev); - return ev; } /* - destroy an events context, also destroying any remaining events -*/ -void event_context_destroy(struct event_context *ev) -{ - talloc_free(ev); -} - - -/* recalculate the maxfd */ static void calc_maxfd(struct event_context *ev) @@ -131,17 +150,25 @@ static int event_fd_destructor(void *ptr) 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 *e0, - TALLOC_CTX *mem_ctx) +struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, event_fd_handler_t handler, + void *private) { - struct fd_event *e = talloc(ev->events, struct fd_event); + struct fd_event *e = talloc(ev, struct fd_event); if (!e) return NULL; - *e = *e0; - DLIST_ADD(ev->fd_events, e); + e->event_ctx = ev; + e->fd = fd; + e->flags = flags; + e->handler = handler; + e->private = private; + + DLIST_ADD(ev->fd_events, e); + if (e->fd > ev->maxfd) { ev->maxfd = e->fd; } + talloc_set_destructor(e, event_fd_destructor); if (mem_ctx) { talloc_steal(mem_ctx, e); @@ -150,54 +177,52 @@ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0, } -static int event_timed_destructor(void *ptr) +/* + return the fd event flags +*/ +uint16_t event_fd_flags(struct fd_event *fde) { - 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; + return fde->flags; } /* - add a timed event - return NULL on failure (memory allocation error) + set the fd event flags */ -struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e0, - TALLOC_CTX *mem_ctx) +void event_fd_setflags(struct fd_event *fde, uint16_t flags) { - struct timed_event *e = talloc(ev->events, struct timed_event); - if (!e) return NULL; - *e = *e0; - e->event_ctx = ev; - DLIST_ADD(ev->timed_events, e); - talloc_set_destructor(e, event_timed_destructor); - if (mem_ctx) { - talloc_steal(mem_ctx, e); - } - return e; + fde->flags = flags; } -static int event_loop_destructor(void *ptr) +/* + destroy a timed event +*/ +static int event_timed_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++; + 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 loop event + add a timed event return NULL on failure (memory allocation error) */ -struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e0, - TALLOC_CTX *mem_ctx) +struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private) { - struct loop_event *e = talloc(ev->events, struct loop_event); + struct timed_event *e = talloc(ev, struct timed_event); if (!e) return NULL; - *e = *e0; - e->event_ctx = ev; - DLIST_ADD(ev->loop_events, e); - talloc_set_destructor(e, event_loop_destructor); + + e->event_ctx = ev; + e->next_event = next_event; + e->handler = handler; + e->private = private; + + DLIST_ADD(ev->timed_events, e); + talloc_set_destructor(e, event_timed_destructor); if (mem_ctx) { talloc_steal(mem_ctx, e); } @@ -205,38 +230,17 @@ struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e } /* - tell the event loop to exit with the specified code -*/ -void event_loop_exit(struct event_context *ev, int code) -{ - ev->exit.exit_now = True; - ev->exit.code = code; -} - -/* do a single event loop using the events defined in ev this function */ int event_loop_once(struct event_context *ev) { fd_set r_fds, w_fds; struct fd_event *fe; - struct loop_event *le; struct timed_event *te, *te_next; int selrtn; - struct timeval tval, t, *tvalp=NULL; + struct timeval tval, t, *tvalp; uint32_t destruction_count = ev->destruction_count; - t = timeval_current(); - - /* the loop events are called on each loop. Be careful to allow the - event to remove itself */ - for (le=ev->loop_events;le;) { - struct loop_event *next = le->next; - le->handler(ev, le, t); - if (destruction_count != ev->destruction_count) break; - le = next; - } - FD_ZERO(&r_fds); FD_ZERO(&w_fds); @@ -252,9 +256,8 @@ int event_loop_once(struct event_context *ev) fe = next; } - /* start with a reasonable max timeout */ - tval.tv_sec = 0; - tval.tv_usec = 0; + tvalp = NULL; + t = timeval_current(); /* work out the right timeout for all timed events */ for (te=ev->timed_events;te;te=te_next) { @@ -301,7 +304,7 @@ int event_loop_once(struct event_context *ev) the event, so this must be a bug. This is a fatal error. */ DEBUG(0,("EBADF on event_loop_once - exiting\n")); - ev->exit.code = EBADF; + ev->exit_code = EBADF; return -1; } @@ -314,7 +317,7 @@ int event_loop_once(struct event_context *ev) if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; if (flags) { - fe->handler(ev, fe, t, flags); + fe->handler(ev, fe, t, flags, fe->private); if (destruction_count != ev->destruction_count) { break; } @@ -328,7 +331,7 @@ int event_loop_once(struct event_context *ev) struct timed_event *next = te->next; if (timeval_compare(&te->next_event, &t) >= 0) { te->next_event = timeval_zero(); - te->handler(ev, te, t); + te->handler(ev, te, t, te->private); if (destruction_count != ev->destruction_count) { break; } @@ -348,16 +351,14 @@ int event_loop_once(struct event_context *ev) */ int event_loop_wait(struct event_context *ev) { - ZERO_STRUCT(ev->exit); + ev->exit_code = 0; ev->maxfd = EVENT_INVALID_MAXFD; - ev->exit.exit_now = False; - - while (ev->fd_events && !ev->exit.exit_now) { + while (ev->fd_events && ev->exit_code == 0) { if (event_loop_once(ev) != 0) { break; } } - return ev->exit.code; + return ev->exit_code; } |