2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 struct timed_event *next, *prev;
26 struct event_context *event_ctx;
28 const char *event_name;
29 void (*handler)(struct event_context *event_ctx,
30 struct timed_event *te,
31 const struct timeval *now,
37 struct fd_event *prev, *next;
38 struct event_context *event_ctx;
40 uint16_t flags; /* see EVENT_FD_* flags */
41 void (*handler)(struct event_context *event_ctx,
42 struct fd_event *event,
48 #define EVENT_FD_WRITEABLE(fde) \
49 event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_WRITE)
50 #define EVENT_FD_READABLE(fde) \
51 event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_READ)
53 #define EVENT_FD_NOT_WRITEABLE(fde) \
54 event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE)
55 #define EVENT_FD_NOT_READABLE(fde) \
56 event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_READ)
58 struct event_context {
59 struct timed_event *timed_events;
60 struct fd_event *fd_events;
63 static int timed_event_destructor(struct timed_event *te)
65 DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te,
67 DLIST_REMOVE(te->event_ctx->timed_events, te);
71 /****************************************************************************
73 ****************************************************************************/
75 static void add_event_by_time(struct timed_event *te)
77 struct event_context *ctx = te->event_ctx;
78 struct timed_event *last_te, *cur_te;
80 /* Keep the list ordered by time. We must preserve this. */
82 for (cur_te = ctx->timed_events; cur_te; cur_te = cur_te->next) {
83 /* if the new event comes before the current one break */
84 if (!timeval_is_zero(&cur_te->when) &&
85 timeval_compare(&te->when, &cur_te->when) < 0) {
91 DLIST_ADD_AFTER(ctx->timed_events, te, last_te);
94 /****************************************************************************
95 Schedule a function for future calling, cancel with TALLOC_FREE().
96 It's the responsibility of the handler to call TALLOC_FREE() on the event
98 ****************************************************************************/
100 struct timed_event *event_add_timed(struct event_context *event_ctx,
103 const char *event_name,
104 void (*handler)(struct event_context *event_ctx,
105 struct timed_event *te,
106 const struct timeval *now,
110 struct timed_event *te;
112 te = TALLOC_P(mem_ctx, struct timed_event);
114 DEBUG(0, ("talloc failed\n"));
118 te->event_ctx = event_ctx;
120 te->event_name = event_name;
121 te->handler = handler;
122 te->private_data = private_data;
124 add_event_by_time(te);
126 talloc_set_destructor(te, timed_event_destructor);
128 DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name,
133 static int fd_event_destructor(struct fd_event *fde)
135 struct event_context *event_ctx = fde->event_ctx;
137 DLIST_REMOVE(event_ctx->fd_events, fde);
141 struct fd_event *event_add_fd(struct event_context *event_ctx,
143 int fd, uint16_t flags,
144 void (*handler)(struct event_context *event_ctx,
145 struct fd_event *event,
150 struct fd_event *fde;
152 if (!(fde = TALLOC_P(mem_ctx, struct fd_event))) {
156 fde->event_ctx = event_ctx;
159 fde->handler = handler;
160 fde->private_data = private_data;
162 DLIST_ADD(event_ctx->fd_events, fde);
164 talloc_set_destructor(fde, fd_event_destructor);
168 void event_fd_set_writeable(struct fd_event *fde)
170 fde->flags |= EVENT_FD_WRITE;
173 void event_fd_set_not_writeable(struct fd_event *fde)
175 fde->flags &= ~EVENT_FD_WRITE;
178 void event_fd_set_readable(struct fd_event *fde)
180 fde->flags |= EVENT_FD_READ;
183 void event_fd_set_not_readable(struct fd_event *fde)
185 fde->flags &= ~EVENT_FD_READ;
189 * Return if there's something in the queue
192 BOOL event_add_to_select_args(struct event_context *event_ctx,
193 const struct timeval *now,
194 fd_set *read_fds, fd_set *write_fds,
195 struct timeval *timeout, int *maxfd)
197 struct fd_event *fde;
201 for (fde = event_ctx->fd_events; fde; fde = fde->next) {
202 if (fde->flags & EVENT_FD_READ) {
203 FD_SET(fde->fd, read_fds);
206 if (fde->flags & EVENT_FD_WRITE) {
207 FD_SET(fde->fd, write_fds);
211 if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE))
212 && (fde->fd > *maxfd)) {
217 if (event_ctx->timed_events == NULL) {
221 diff = timeval_until(now, &event_ctx->timed_events->when);
222 *timeout = timeval_min(timeout, &diff);
227 BOOL events_pending(struct event_context *event_ctx)
229 struct fd_event *fde;
231 if (event_ctx->timed_events != NULL) {
234 for (fde = event_ctx->fd_events; fde; fde = fde->next) {
235 if (fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) {
242 BOOL run_events(struct event_context *event_ctx,
243 int selrtn, fd_set *read_fds, fd_set *write_fds)
246 struct fd_event *fde, *next;
248 /* Run all events that are pending, not just one (as we
251 while (event_ctx->timed_events) {
256 &now, &event_ctx->timed_events->when) < 0) {
257 /* Nothing to do yet */
258 DEBUG(11, ("run_events: Nothing to do\n"));
262 DEBUG(10, ("Running event \"%s\" %lx\n",
263 event_ctx->timed_events->event_name,
264 (unsigned long)event_ctx->timed_events));
266 event_ctx->timed_events->handler(
268 event_ctx->timed_events, &now,
269 event_ctx->timed_events->private_data);
276 * We might have changed the socket status during the timed
277 * events, return to run select again.
289 for (fde = event_ctx->fd_events; fde; fde = next) {
293 if (FD_ISSET(fde->fd, read_fds)) flags |= EVENT_FD_READ;
294 if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE;
297 fde->handler(event_ctx, fde, flags, fde->private_data);
306 struct timeval *get_timed_events_timeout(struct event_context *event_ctx,
307 struct timeval *to_ret)
311 if (event_ctx->timed_events == NULL) {
315 now = timeval_current();
316 *to_ret = timeval_until(&now, &event_ctx->timed_events->when);
318 DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret->tv_sec,
319 (int)to_ret->tv_usec));
324 int event_loop_once(struct event_context *ev)
326 struct timeval now, to;
334 to.tv_sec = 9999; /* Max timeout */
339 if (!event_add_to_select_args(ev, &now, &r_fds, &w_fds, &to, &maxfd)) {
343 if (timeval_is_zero(&to)) {
344 run_events(ev, 0, NULL, NULL);
348 ret = sys_select(maxfd, &r_fds, &w_fds, NULL, &to);
350 if (ret == -1 && errno != EINTR) {
354 run_events(ev, ret, &r_fds, &w_fds);
358 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
360 return TALLOC_ZERO_P(NULL, struct event_context);
363 int set_event_dispatch_time(struct event_context *event_ctx,
364 const char *event_name, struct timeval when)
366 struct timed_event *te;
368 for (te = event_ctx->timed_events; te; te = te->next) {
369 if (strcmp(event_name, te->event_name) == 0) {
370 DLIST_REMOVE(event_ctx->timed_events, te);
372 add_event_by_time(te);
379 /* Returns 1 if event was found and cancelled, 0 otherwise. */
381 int cancel_named_event(struct event_context *event_ctx,
382 const char *event_name)
384 struct timed_event *te;
386 for (te = event_ctx->timed_events; te; te = te->next) {
387 if (strcmp(event_name, te->event_name) == 0) {