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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 PLEASE READ THIS BEFORE MODIFYING!
24 This module is a general abstraction for the main select loop and
25 event handling. Do not ever put any localised hacks in here, instead
26 register one of the possible event types and implement that event
29 There are 2 types of event handling that are handled in this module:
31 1) a file descriptor becoming readable or writeable. This is mostly
32 used for network sockets, but can be used for any type of file
33 descriptor. You may only register one handler for each file
34 descriptor/io combination or you will get unpredictable results
35 (this means that you can have a handler for read events, and a
36 separate handler for write events, but not two handlers that are
37 both handling read events)
39 2) a timed event. You can register an event that happens at a
40 specific time. You can register as many of these as you
41 like. They are single shot - add a new timed event in the event
42 handler to get another event.
44 To setup a set of events you first need to create a event_context
45 structure using the function event_context_init(); This returns a
46 'struct event_context' that you use in all subsequent calls.
48 After that you can add/remove events that you are interested in
49 using event_add_*() and talloc_free()
51 Finally, you call event_loop_wait_once() to block waiting for one of the
52 events to occor or event_loop_wait() which will loop
58 #include "lib/events/events.h"
59 #include "lib/events/events_internal.h"
60 #include "lib/util/dlinklist.h"
65 struct event_ops_list {
66 struct event_ops_list *next, *prev;
68 const struct event_ops *ops;
71 /* list of registered event backends */
72 static struct event_ops_list *event_backends;
75 register an events backend
77 bool event_register_backend(const char *name, const struct event_ops *ops)
79 struct event_ops_list *e;
80 e = talloc(talloc_autofree_context(), struct event_ops_list);
81 if (e == NULL) return False;
84 DLIST_ADD(event_backends, e);
89 initialise backends if not already done
91 static void event_backend_init(void)
94 init_module_fn static_init[] = STATIC_LIBEVENTS_MODULES;
95 init_module_fn *shared_init;
96 if (event_backends) return;
97 shared_init = load_samba_modules(NULL, "LIBEVENTS");
98 run_init_functions(static_init);
99 run_init_functions(shared_init);
101 bool events_standard_init(void);
102 events_standard_init();
107 list available backends
109 const char **event_backend_list(TALLOC_CTX *mem_ctx)
111 const char **list = NULL;
112 struct event_ops_list *e;
114 event_backend_init();
116 for (e=event_backends;e;e=e->next) {
117 list = str_list_add(list, e->name);
120 talloc_steal(mem_ctx, list);
126 create a event_context structure for a specific implemementation.
127 This must be the first events call, and all subsequent calls pass
128 this event_context as the first element. Event handlers also
129 receive this as their first argument.
131 This function is for allowing third-party-applications to hook in gluecode
132 to their own event loop code, so that they can make async usage of our client libs
134 NOTE: use event_context_init() inside of samba!
136 static struct event_context *event_context_init_ops(TALLOC_CTX *mem_ctx,
137 const struct event_ops *ops)
139 struct event_context *ev;
142 ev = talloc_zero(mem_ctx, struct event_context);
143 if (!ev) return NULL;
147 ret = ev->ops->context_init(ev);
157 create a event_context structure. This must be the first events
158 call, and all subsequent calls pass this event_context as the first
159 element. Event handlers also receive this as their first argument.
161 struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char *name)
163 struct event_ops_list *e;
165 event_backend_init();
169 name = lp_parm_string(-1, "event", "backend");
176 for (e=event_backends;e;e=e->next) {
177 if (strcmp(name, e->name) == 0) {
178 return event_context_init_ops(mem_ctx, e->ops);
186 create a event_context structure. This must be the first events
187 call, and all subsequent calls pass this event_context as the first
188 element. Event handlers also receive this as their first argument.
190 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
192 return event_context_init_byname(mem_ctx, NULL);
197 return NULL on failure (memory allocation error)
199 struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
200 int fd, uint16_t flags, event_fd_handler_t handler,
203 return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data);
209 struct aio_event *event_add_aio(struct event_context *ev,
212 event_aio_handler_t handler,
215 if (ev->ops->add_aio == NULL) return NULL;
216 return ev->ops->add_aio(ev, mem_ctx, iocb, handler, private_data);
220 return the fd event flags
222 uint16_t event_get_fd_flags(struct fd_event *fde)
225 return fde->event_ctx->ops->get_fd_flags(fde);
229 set the fd event flags
231 void event_set_fd_flags(struct fd_event *fde, uint16_t flags)
234 fde->event_ctx->ops->set_fd_flags(fde, flags);
239 return NULL on failure
241 struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
242 struct timeval next_event,
243 event_timed_handler_t handler,
246 return ev->ops->add_timed(ev, mem_ctx, next_event, handler, private_data);
252 sa_flags are flags to sigaction(2)
254 return NULL on failure
256 struct signal_event *event_add_signal(struct event_context *ev, TALLOC_CTX *mem_ctx,
259 event_signal_handler_t handler,
262 return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data);
266 do a single event loop using the events defined in ev
268 _PUBLIC_ int event_loop_once(struct event_context *ev)
270 return ev->ops->loop_once(ev);
274 return on failure or (with 0) if all fd events are removed
276 int event_loop_wait(struct event_context *ev)
278 return ev->ops->loop_wait(ev);
282 find an event context that is a parent of the given memory context,
283 or create a new event context as a child of the given context if
286 This should be used in preference to event_context_init() in places
287 where you would prefer to use the existing event context if possible
288 (which is most situations)
290 struct event_context *event_context_find(TALLOC_CTX *mem_ctx)
292 struct event_context *ev = talloc_find_parent_bytype(mem_ctx, struct event_context);
294 ev = event_context_init(mem_ctx);