Avoid including events_util.h in events_internal.h since the latter is
[Samba/gbeck.git] / source4 / lib / events / events.c
blob52699d968e72889d903d1a0b86ac77812b53e1f5
1 /*
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
26 somewhere else.
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
52 forever.
55 #include "replace.h"
56 #include "events.h"
57 #include "events_internal.h"
58 #include "events_util.h"
60 struct event_ops_list {
61 struct event_ops_list *next, *prev;
62 const char *name;
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 */
80 return true;
84 e = talloc(talloc_autofree_context(), struct event_ops_list);
85 if (e == NULL) return false;
87 e->name = name;
88 e->ops = ops;
89 DLIST_ADD(event_backends, e);
91 return true;
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
111 events_epoll_init();
112 #endif
113 #if HAVE_LINUX_AIO
114 events_aio_init();
115 #endif
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);
134 return 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;
152 int ret;
154 ev = talloc_zero(mem_ctx, struct event_context);
155 if (!ev) return NULL;
157 ev->ops = ops;
159 ret = ev->ops->context_init(ev);
160 if (ret != 0) {
161 talloc_free(ev);
162 return NULL;
165 return 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();
179 if (name == NULL) {
180 name = event_default_backend;
182 if (name == NULL) {
183 name = "standard";
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);
191 return NULL;
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);
206 add a fd based event
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,
214 void *private_data)
216 return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data);
220 add a disk aio event
222 struct aio_event *event_add_aio(struct event_context *ev,
223 TALLOC_CTX *mem_ctx,
224 struct iocb *iocb,
225 event_aio_handler_t handler,
226 void *private_data)
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)
237 if (!fde) return 0;
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)
246 if (!fde) return;
247 fde->event_ctx->ops->set_fd_flags(fde, flags);
251 add a timed event
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,
257 void *private_data)
259 return ev->ops->add_timed(ev, mem_ctx, next_event, handler, private_data);
263 add a signal event
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,
270 int signum,
271 int sa_flags,
272 event_signal_handler_t handler,
273 void *private_data)
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
297 none is found
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);
306 if (ev == NULL) {
307 ev = event_context_init(mem_ctx);
309 return ev;