2 Unix SMB/CIFS implementation.
3 main select loop and event handling
4 Copyright (C) Andrew Tridgell 2003
5 Copyright (C) Stefan Metzmacher 2009
7 ** NOTE! The following LGPL license applies to the tevent
8 ** library. This does NOT imply that all of Samba is released
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 PLEASE READ THIS BEFORE MODIFYING!
28 This module is a general abstraction for the main select loop and
29 event handling. Do not ever put any localised hacks in here, instead
30 register one of the possible event types and implement that event
33 There are 2 types of event handling that are handled in this module:
35 1) a file descriptor becoming readable or writeable. This is mostly
36 used for network sockets, but can be used for any type of file
37 descriptor. You may only register one handler for each file
38 descriptor/io combination or you will get unpredictable results
39 (this means that you can have a handler for read events, and a
40 separate handler for write events, but not two handlers that are
41 both handling read events)
43 2) a timed event. You can register an event that happens at a
44 specific time. You can register as many of these as you
45 like. They are single shot - add a new timed event in the event
46 handler to get another event.
48 To setup a set of events you first need to create a event_context
49 structure using the function tevent_context_init(); This returns a
50 'struct tevent_context' that you use in all subsequent calls.
52 After that you can add/remove events that you are interested in
53 using tevent_add_*() and talloc_free()
55 Finally, you call tevent_loop_wait_once() to block waiting for one of the
56 events to occor or tevent_loop_wait() which will loop
61 #include "system/filesys.h"
63 #include "tevent_internal.h"
64 #include "tevent_util.h"
66 struct tevent_ops_list {
67 struct tevent_ops_list *next, *prev;
69 const struct tevent_ops *ops;
72 /* list of registered event backends */
73 static struct tevent_ops_list *tevent_backends = NULL;
74 static char *tevent_default_backend = NULL;
77 register an events backend
79 bool tevent_register_backend(const char *name, const struct tevent_ops *ops)
81 struct tevent_ops_list *e;
83 for (e = tevent_backends; e != NULL; e = e->next) {
84 if (0 == strcmp(e->name, name)) {
85 /* already registered, skip it */
90 e = talloc(talloc_autofree_context(), struct tevent_ops_list);
91 if (e == NULL) return false;
95 DLIST_ADD(tevent_backends, e);
101 set the default event backend
103 void tevent_set_default_backend(const char *backend)
105 talloc_free(tevent_default_backend);
106 tevent_default_backend = talloc_strdup(talloc_autofree_context(),
111 initialise backends if not already done
113 static void tevent_backend_init(void)
115 tevent_select_init();
116 tevent_standard_init();
123 list available backends
125 const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
127 const char **list = NULL;
128 struct tevent_ops_list *e;
130 tevent_backend_init();
132 for (e=tevent_backends;e;e=e->next) {
133 list = ev_str_list_add(list, e->name);
136 talloc_steal(mem_ctx, list);
141 int tevent_common_context_destructor(struct tevent_context *ev)
143 struct tevent_fd *fd, *fn;
144 struct tevent_timer *te, *tn;
145 struct tevent_signal *se, *sn;
148 talloc_free(ev->pipe_fde);
152 for (fd = ev->fd_events; fd; fd = fn) {
154 fd->event_ctx = NULL;
155 DLIST_REMOVE(ev->fd_events, fd);
158 for (te = ev->timer_events; te; te = tn) {
160 te->event_ctx = NULL;
161 DLIST_REMOVE(ev->timer_events, te);
164 for (se = ev->signal_events; se; se = sn) {
166 se->event_ctx = NULL;
167 DLIST_REMOVE(ev->signal_events, se);
174 create a event_context structure for a specific implemementation.
175 This must be the first events call, and all subsequent calls pass
176 this event_context as the first element. Event handlers also
177 receive this as their first argument.
179 This function is for allowing third-party-applications to hook in gluecode
180 to their own event loop code, so that they can make async usage of our client libs
182 NOTE: use tevent_context_init() inside of samba!
184 static struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
185 const struct tevent_ops *ops)
187 struct tevent_context *ev;
190 ev = talloc_zero(mem_ctx, struct tevent_context);
191 if (!ev) return NULL;
193 talloc_set_destructor(ev, tevent_common_context_destructor);
197 ret = ev->ops->context_init(ev);
207 create a event_context structure. This must be the first events
208 call, and all subsequent calls pass this event_context as the first
209 element. Event handlers also receive this as their first argument.
211 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
214 struct tevent_ops_list *e;
216 tevent_backend_init();
219 name = tevent_default_backend;
225 for (e=tevent_backends;e;e=e->next) {
226 if (strcmp(name, e->name) == 0) {
227 return tevent_context_init_ops(mem_ctx, e->ops);
235 create a event_context structure. This must be the first events
236 call, and all subsequent calls pass this event_context as the first
237 element. Event handlers also receive this as their first argument.
239 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
241 return tevent_context_init_byname(mem_ctx, NULL);
246 return NULL on failure (memory allocation error)
248 if flags contains TEVENT_FD_AUTOCLOSE then the fd will be closed when
249 the returned fd_event context is freed
251 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
255 tevent_fd_handler_t handler,
257 const char *handler_name,
258 const char *location)
260 return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
261 handler_name, location);
265 set a close function on the fd event
267 void tevent_fd_set_close_fn(struct tevent_fd *fde,
268 tevent_fd_close_fn_t close_fn)
271 if (!fde->event_ctx) return;
272 fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
275 static void tevent_fd_auto_close_fn(struct tevent_context *ev,
276 struct tevent_fd *fde,
283 void tevent_fd_set_auto_close(struct tevent_fd *fde)
285 tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
289 return the fd event flags
291 uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
294 if (!fde->event_ctx) return 0;
295 return fde->event_ctx->ops->get_fd_flags(fde);
299 set the fd event flags
301 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
304 if (!fde->event_ctx) return;
305 fde->event_ctx->ops->set_fd_flags(fde, flags);
310 return NULL on failure
312 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
314 struct timeval next_event,
315 tevent_timer_handler_t handler,
317 const char *handler_name,
318 const char *location)
320 return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
321 handler_name, location);
327 sa_flags are flags to sigaction(2)
329 return NULL on failure
331 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
335 tevent_signal_handler_t handler,
337 const char *handler_name,
338 const char *location)
340 return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
341 handler_name, location);
345 do a single event loop using the events defined in ev
347 int tevent_loop_once(struct tevent_context *ev)
349 return ev->ops->loop_once(ev);
353 return on failure or (with 0) if all fd events are removed
355 int tevent_loop_wait(struct tevent_context *ev)
357 return ev->ops->loop_wait(ev);