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
;
188 void event_add_to_select_args(struct event_context
*event_ctx
,
189 const struct timeval
*now
,
190 fd_set
*read_fds
, fd_set
*write_fds
,
191 struct timeval
*timeout
, int *maxfd
)
193 struct fd_event
*fde
;
196 for (fde
= event_ctx
->fd_events
; fde
; fde
= fde
->next
) {
197 if (fde
->flags
& EVENT_FD_READ
) {
198 FD_SET(fde
->fd
, read_fds
);
200 if (fde
->flags
& EVENT_FD_WRITE
) {
201 FD_SET(fde
->fd
, write_fds
);
204 if ((fde
->flags
& (EVENT_FD_READ
|EVENT_FD_WRITE
))
205 && (fde
->fd
> *maxfd
)) {
210 if (event_ctx
->timed_events
== NULL
) {
214 diff
= timeval_until(now
, &event_ctx
->timed_events
->when
);
215 *timeout
= timeval_min(timeout
, &diff
);
218 BOOL
run_events(struct event_context
*event_ctx
,
219 int selrtn
, fd_set
*read_fds
, fd_set
*write_fds
)
222 struct fd_event
*fde
, *next
;
224 /* Run all events that are pending, not just one (as we
227 while (event_ctx
->timed_events
) {
232 &now
, &event_ctx
->timed_events
->when
) < 0) {
233 /* Nothing to do yet */
234 DEBUG(11, ("run_events: Nothing to do\n"));
238 DEBUG(10, ("Running event \"%s\" %lx\n",
239 event_ctx
->timed_events
->event_name
,
240 (unsigned long)event_ctx
->timed_events
));
242 event_ctx
->timed_events
->handler(
244 event_ctx
->timed_events
, &now
,
245 event_ctx
->timed_events
->private_data
);
252 * We might have changed the socket status during the timed
253 * events, return to run select again.
265 for (fde
= event_ctx
->fd_events
; fde
; fde
= next
) {
269 if (FD_ISSET(fde
->fd
, read_fds
)) flags
|= EVENT_FD_READ
;
270 if (FD_ISSET(fde
->fd
, write_fds
)) flags
|= EVENT_FD_WRITE
;
273 fde
->handler(event_ctx
, fde
, flags
, fde
->private_data
);
282 struct timeval
*get_timed_events_timeout(struct event_context
*event_ctx
,
283 struct timeval
*to_ret
)
287 if (event_ctx
->timed_events
== NULL
) {
291 now
= timeval_current();
292 *to_ret
= timeval_until(&now
, &event_ctx
->timed_events
->when
);
294 DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret
->tv_sec
,
295 (int)to_ret
->tv_usec
));
300 static int event_context_destructor(struct event_context
*ev
)
302 while (ev
->fd_events
!= NULL
) {
303 ev
->fd_events
->event_ctx
= NULL
;
304 DLIST_REMOVE(ev
->fd_events
, ev
->fd_events
);
306 while (ev
->timed_events
!= NULL
) {
307 ev
->timed_events
->event_ctx
= NULL
;
308 DLIST_REMOVE(ev
->timed_events
, ev
->timed_events
);
313 void event_context_reinit(struct event_context
*ev
)
315 event_context_destructor(ev
);
319 struct event_context
*event_context_init(TALLOC_CTX
*mem_ctx
)
321 struct event_context
*result
;
323 result
= TALLOC_ZERO_P(mem_ctx
, struct event_context
);
324 if (result
== NULL
) {
328 talloc_set_destructor(result
, event_context_destructor
);