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
57 #include "tevent_internal.h"
58 #include "tevent_util.h"
60 struct tevent_ops_list {
61 struct tevent_ops_list *next, *prev;
63 const struct tevent_ops *ops;
66 /* list of registered event backends */
67 static struct tevent_ops_list *tevent_backends = NULL;
68 static char *tevent_default_backend = NULL;
71 register an events backend
73 bool tevent_register_backend(const char *name, const struct tevent_ops *ops)
75 struct tevent_ops_list *e;
77 for (e = tevent_backends; e != NULL; e = e->next) {
78 if (0 == strcmp(e->name, name)) {
79 /* already registered, skip it */
84 e = talloc(talloc_autofree_context(), struct tevent_ops_list);
85 if (e == NULL) return false;
89 DLIST_ADD(tevent_backends, e);
95 set the default event backend
97 void tevent_set_default_backend(const char *backend)
99 talloc_free(tevent_default_backend);
100 tevent_default_backend = talloc_strdup(talloc_autofree_context(),
105 initialise backends if not already done
107 static void tevent_backend_init(void)
109 tevent_select_init();
110 tevent_standard_init();
114 #ifdef HAVE_LINUX_AIO
120 list available backends
122 const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
124 const char **list = NULL;
125 struct tevent_ops_list *e;
127 tevent_backend_init();
129 for (e=tevent_backends;e;e=e->next) {
130 list = ev_str_list_add(list, e->name);
133 talloc_steal(mem_ctx, list);
139 create a event_context structure for a specific implemementation.
140 This must be the first events call, and all subsequent calls pass
141 this event_context as the first element. Event handlers also
142 receive this as their first argument.
144 This function is for allowing third-party-applications to hook in gluecode
145 to their own event loop code, so that they can make async usage of our client libs
147 NOTE: use tevent_context_init() inside of samba!
149 static struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
150 const struct tevent_ops *ops)
152 struct tevent_context *ev;
155 ev = talloc_zero(mem_ctx, struct tevent_context);
156 if (!ev) return NULL;
160 ret = ev->ops->context_init(ev);
170 create a event_context structure. This must be the first events
171 call, and all subsequent calls pass this event_context as the first
172 element. Event handlers also receive this as their first argument.
174 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
177 struct tevent_ops_list *e;
179 tevent_backend_init();
182 name = tevent_default_backend;
188 for (e=tevent_backends;e;e=e->next) {
189 if (strcmp(name, e->name) == 0) {
190 return tevent_context_init_ops(mem_ctx, e->ops);
198 create a event_context structure. This must be the first events
199 call, and all subsequent calls pass this event_context as the first
200 element. Event handlers also receive this as their first argument.
202 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
204 return tevent_context_init_byname(mem_ctx, NULL);
209 return NULL on failure (memory allocation error)
211 if flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when
212 the returned fd_event context is freed
214 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
218 tevent_fd_handler_t handler,
220 const char *handler_name,
221 const char *location)
223 return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
224 handler_name, location);
230 struct tevent_aio *_tevent_add_aio(struct tevent_context *ev,
233 tevent_aio_handler_t handler,
235 const char *handler_name,
236 const char *location)
238 if (ev->ops->add_aio == NULL) return NULL;
239 return ev->ops->add_aio(ev, mem_ctx, iocb, handler, private_data,
240 handler_name, location);
244 set a close function on the fd event
246 void tevent_fd_set_close_fn(struct tevent_fd *fde,
247 tevent_fd_close_fn_t close_fn)
250 fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
254 return the fd event flags
256 uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
259 return fde->event_ctx->ops->get_fd_flags(fde);
263 set the fd event flags
265 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
268 fde->event_ctx->ops->set_fd_flags(fde, flags);
273 return NULL on failure
275 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
277 struct timeval next_event,
278 tevent_timer_handler_t handler,
280 const char *handler_name,
281 const char *location)
283 return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
284 handler_name, location);
290 sa_flags are flags to sigaction(2)
292 return NULL on failure
294 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
298 tevent_signal_handler_t handler,
300 const char *handler_name,
301 const char *location)
303 return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
304 handler_name, location);
308 do a single event loop using the events defined in ev
310 int tevent_loop_once(struct tevent_context *ev)
312 return ev->ops->loop_once(ev);
316 return on failure or (with 0) if all fd events are removed
318 int tevent_loop_wait(struct tevent_context *ev)
320 return ev->ops->loop_wait(ev);