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 event_context_init(); This returns a
45 'struct event_context' that you use in all subsequent calls.
47 After that you can add/remove events that you are interested in
48 using event_add_*() and talloc_free()
50 Finally, you call event_loop_wait_once() to block waiting for one of the
51 events to occor or event_loop_wait() which will loop
57 #include "tevent_internal.h"
58 #include "tevent_util.h"
60 struct event_ops_list {
61 struct event_ops_list *next, *prev;
63 const struct event_ops *ops;
66 /* list of registered event backends */
67 static struct event_ops_list *event_backends = NULL;
68 static char *event_default_backend = NULL;
71 register an events backend
73 bool event_register_backend(const char *name, const struct event_ops *ops)
75 struct event_ops_list *e;
77 for (e = event_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 event_ops_list);
85 if (e == NULL) return false;
89 DLIST_ADD(event_backends, e);
95 set the default event backend
97 void event_set_default_backend(const char *backend)
99 if (event_default_backend) free(event_default_backend);
100 event_default_backend = strdup(backend);
104 initialise backends if not already done
106 static void event_backend_init(void)
108 events_select_init();
109 events_standard_init();
110 #if HAVE_EVENTS_EPOLL
119 list available backends
121 const char **event_backend_list(TALLOC_CTX *mem_ctx)
123 const char **list = NULL;
124 struct event_ops_list *e;
126 event_backend_init();
128 for (e=event_backends;e;e=e->next) {
129 list = ev_str_list_add(list, e->name);
132 talloc_steal(mem_ctx, list);
138 create a event_context structure for a specific implemementation.
139 This must be the first events call, and all subsequent calls pass
140 this event_context as the first element. Event handlers also
141 receive this as their first argument.
143 This function is for allowing third-party-applications to hook in gluecode
144 to their own event loop code, so that they can make async usage of our client libs
146 NOTE: use event_context_init() inside of samba!
148 static struct event_context *event_context_init_ops(TALLOC_CTX *mem_ctx,
149 const struct event_ops *ops)
151 struct event_context *ev;
154 ev = talloc_zero(mem_ctx, struct event_context);
155 if (!ev) return NULL;
159 ret = ev->ops->context_init(ev);
169 create a event_context structure. This must be the first events
170 call, and all subsequent calls pass this event_context as the first
171 element. Event handlers also receive this as their first argument.
173 struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char *name)
175 struct event_ops_list *e;
177 event_backend_init();
180 name = event_default_backend;
186 for (e=event_backends;e;e=e->next) {
187 if (strcmp(name, e->name) == 0) {
188 return event_context_init_ops(mem_ctx, e->ops);
196 create a event_context structure. This must be the first events
197 call, and all subsequent calls pass this event_context as the first
198 element. Event handlers also receive this as their first argument.
200 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
202 return event_context_init_byname(mem_ctx, NULL);
207 return NULL on failure (memory allocation error)
209 if flags contains EVENT_FD_AUTOCLOSE then the fd will be closed when
210 the returned fd_event context is freed
212 struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
213 int fd, uint16_t flags, event_fd_handler_t handler,
216 return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data);
222 struct aio_event *event_add_aio(struct event_context *ev,
225 event_aio_handler_t handler,
228 if (ev->ops->add_aio == NULL) return NULL;
229 return ev->ops->add_aio(ev, mem_ctx, iocb, handler, private_data);
233 return the fd event flags
235 uint16_t event_get_fd_flags(struct fd_event *fde)
238 return fde->event_ctx->ops->get_fd_flags(fde);
242 set the fd event flags
244 void event_set_fd_flags(struct fd_event *fde, uint16_t flags)
247 fde->event_ctx->ops->set_fd_flags(fde, flags);
252 return NULL on failure
254 struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
255 struct timeval next_event,
256 event_timed_handler_t handler,
259 return ev->ops->add_timed(ev, mem_ctx, next_event, handler, private_data);
265 sa_flags are flags to sigaction(2)
267 return NULL on failure
269 struct signal_event *event_add_signal(struct event_context *ev, TALLOC_CTX *mem_ctx,
272 event_signal_handler_t handler,
275 return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data);
279 do a single event loop using the events defined in ev
281 int event_loop_once(struct event_context *ev)
283 return ev->ops->loop_once(ev);
287 return on failure or (with 0) if all fd events are removed
289 int event_loop_wait(struct event_context *ev)
291 return ev->ops->loop_wait(ev);
295 find an event context that is a parent of the given memory context,
296 or create a new event context as a child of the given context if
299 This should be used in preference to event_context_init() in places
300 where you would prefer to use the existing event context if possible
301 (which is most situations)
303 struct event_context *event_context_find(TALLOC_CTX *mem_ctx)
305 struct event_context *ev = talloc_find_parent_bytype(mem_ctx, struct event_context);
307 ev = event_context_init(mem_ctx);