2 Unix SMB/CIFS implementation.
3 main select loop and event handling
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 PLEASE READ THIS BEFORE MODIFYING!
23 This module is a general abstraction for the main select loop and
24 event handling. Do not ever put any localised hacks in here, instead
25 register one of the possible event types and implement that event
28 There are 2 types of event handling that are handled in this module:
30 1) a file descriptor becoming readable or writeable. This is mostly
31 used for network sockets, but can be used for any type of file
32 descriptor. You may only register one handler for each file
33 descriptor/io combination or you will get unpredictable results
34 (this means that you can have a handler for read events, and a
35 separate handler for write events, but not two handlers that are
36 both handling read events)
38 2) a timed event. You can register an event that happens at a
39 specific time. You can register as many of these as you
40 like. They are single shot - add a new timed event in the event
41 handler to get another event.
43 To setup a set of events you first need to create a event_context
44 structure using the function tevent_context_init(); This returns a
45 'struct tevent_context' that you use in all subsequent calls.
47 After that you can add/remove events that you are interested in
48 using tevent_add_*() and talloc_free()
50 Finally, you call tevent_loop_wait_once() to block waiting for one of the
51 events to occor or tevent_loop_wait() which will loop
56 #include "system/filesys.h"
58 #include "tevent_internal.h"
59 #include "tevent_util.h"
61 struct tevent_ops_list {
62 struct tevent_ops_list *next, *prev;
64 const struct tevent_ops *ops;
67 /* list of registered event backends */
68 static struct tevent_ops_list *tevent_backends = NULL;
69 static char *tevent_default_backend = NULL;
72 register an events backend
74 bool tevent_register_backend(const char *name, const struct tevent_ops *ops)
76 struct tevent_ops_list *e;
78 for (e = tevent_backends; e != NULL; e = e->next) {
79 if (0 == strcmp(e->name, name)) {
80 /* already registered, skip it */
85 e = talloc(talloc_autofree_context(), struct tevent_ops_list);
86 if (e == NULL) return false;
90 DLIST_ADD(tevent_backends, e);
96 set the default event backend
98 void tevent_set_default_backend(const char *backend)
100 talloc_free(tevent_default_backend);
101 tevent_default_backend = talloc_strdup(talloc_autofree_context(),
106 initialise backends if not already done
108 static void tevent_backend_init(void)
110 tevent_select_init();
111 tevent_standard_init();
115 #ifdef HAVE_LINUX_AIO
121 list available backends
123 const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
125 const char **list = NULL;
126 struct tevent_ops_list *e;
128 tevent_backend_init();
130 for (e=tevent_backends;e;e=e->next) {
131 list = ev_str_list_add(list, e->name);
134 talloc_steal(mem_ctx, list);
140 create a event_context structure for a specific implemementation.
141 This must be the first events call, and all subsequent calls pass
142 this event_context as the first element. Event handlers also
143 receive this as their first argument.
145 This function is for allowing third-party-applications to hook in gluecode
146 to their own event loop code, so that they can make async usage of our client libs
148 NOTE: use tevent_context_init() inside of samba!
150 static struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
151 const struct tevent_ops *ops)
153 struct tevent_context *ev;
156 ev = talloc_zero(mem_ctx, struct tevent_context);
157 if (!ev) return NULL;
161 ret = ev->ops->context_init(ev);
171 create a event_context structure. This must be the first events
172 call, and all subsequent calls pass this event_context as the first
173 element. Event handlers also receive this as their first argument.
175 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
178 struct tevent_ops_list *e;
180 tevent_backend_init();
183 name = tevent_default_backend;
189 for (e=tevent_backends;e;e=e->next) {
190 if (strcmp(name, e->name) == 0) {
191 return tevent_context_init_ops(mem_ctx, e->ops);
199 create a event_context structure. This must be the first events
200 call, and all subsequent calls pass this event_context as the first
201 element. Event handlers also receive this as their first argument.
203 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
205 return tevent_context_init_byname(mem_ctx, NULL);
210 return NULL on failure (memory allocation error)
212 if flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when
213 the returned fd_event context is freed
215 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
219 tevent_fd_handler_t handler,
221 const char *handler_name,
222 const char *location)
224 return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
225 handler_name, location);
231 struct tevent_aio *_tevent_add_aio(struct tevent_context *ev,
234 tevent_aio_handler_t handler,
236 const char *handler_name,
237 const char *location)
239 if (ev->ops->add_aio == NULL) return NULL;
240 return ev->ops->add_aio(ev, mem_ctx, iocb, handler, private_data,
241 handler_name, location);
245 set a close function on the fd event
247 void tevent_fd_set_close_fn(struct tevent_fd *fde,
248 tevent_fd_close_fn_t close_fn)
251 fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
254 static void tevent_fd_auto_close_fn(struct tevent_context *ev,
255 struct tevent_fd *fde,
262 void tevent_fd_set_auto_close(struct tevent_fd *fde)
264 tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
268 return the fd event flags
270 uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
273 return fde->event_ctx->ops->get_fd_flags(fde);
277 set the fd event flags
279 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
282 fde->event_ctx->ops->set_fd_flags(fde, flags);
287 return NULL on failure
289 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
291 struct timeval next_event,
292 tevent_timer_handler_t handler,
294 const char *handler_name,
295 const char *location)
297 return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
298 handler_name, location);
304 sa_flags are flags to sigaction(2)
306 return NULL on failure
308 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
312 tevent_signal_handler_t handler,
314 const char *handler_name,
315 const char *location)
317 return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
318 handler_name, location);
322 do a single event loop using the events defined in ev
324 int tevent_loop_once(struct tevent_context *ev)
326 return ev->ops->loop_once(ev);
330 return on failure or (with 0) if all fd events are removed
332 int tevent_loop_wait(struct tevent_context *ev)
334 return ev->ops->loop_wait(ev);