ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/event.c
Revision: 1.40
Committed: Tue Jan 6 19:57:32 2009 UTC (15 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.39: +3 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     * libevent compatibility layer
3     *
4 root 1.36 * Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
5 root 1.1 * All rights reserved.
6     *
7 root 1.33 * Redistribution and use in source and binary forms, with or without modifica-
8     * tion, are permitted provided that the following conditions are met:
9     *
10     * 1. Redistributions of source code must retain the above copyright notice,
11     * this list of conditions and the following disclaimer.
12     *
13     * 2. Redistributions in binary form must reproduce the above copyright
14     * notice, this list of conditions and the following disclaimer in the
15     * documentation and/or other materials provided with the distribution.
16     *
17     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
19     * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20     * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
21     * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
25     * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
26     * OF THE POSSIBILITY OF SUCH DAMAGE.
27 root 1.1 *
28 root 1.33 * Alternatively, the contents of this file may be used under the terms of
29     * the GNU General Public License ("GPL") version 2 or any later version,
30     * in which case the provisions of the GPL are applicable instead of
31     * the above. If you wish to allow the use of your version of this file
32     * only under the terms of the GPL and not to allow others to use your
33     * version of this file under the BSD license, indicate your decision
34     * by deleting the provisions above and replace them with the notice
35     * and other provisions required by the GPL. If you do not delete the
36     * provisions above, a recipient may use your version of this file under
37     * either the BSD or the GPL.
38 root 1.1 */
39    
40     #include <stddef.h>
41     #include <stdlib.h>
42 root 1.10 #include <assert.h>
43 root 1.1
44 root 1.24 #ifdef EV_EVENT_H
45     # include EV_EVENT_H
46     #else
47     # include "event.h"
48     #endif
49 root 1.1
50 root 1.9 #if EV_MULTIPLICITY
51     # define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base
52     # define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base
53 root 1.8 #else
54     # define dLOOPev
55     # define dLOOPbase
56     #endif
57 root 1.7
58 root 1.9 /* never accessed, will always be cast from/to ev_loop */
59 root 1.1 struct event_base
60     {
61     int dummy;
62     };
63    
64 root 1.37 static struct event_base *ev_x_cur;
65 root 1.1
66     static void
67 root 1.37 ev_tv_set (struct timeval *tv, ev_tstamp at)
68 root 1.1 {
69     tv->tv_sec = (long)at;
70     tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);
71     }
72    
73     static ev_tstamp
74 root 1.37 ev_tv_get (struct timeval *tv)
75 root 1.1 {
76     if (tv)
77     return tv->tv_sec + tv->tv_usec * 1e-6;
78     else
79     return -1.;
80     }
81    
82 root 1.40 #define EVENT_STRINGIFY(s) # s
83     #define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b)
84 root 1.1
85     const char *event_get_version (void)
86     {
87 root 1.40 /* returns ABI, not API or library, version */
88 root 1.1 return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);
89     }
90    
91     const char *event_get_method (void)
92     {
93     return "libev";
94     }
95    
96     void *event_init (void)
97     {
98 root 1.9 #if EV_MULTIPLICITY
99 root 1.37 if (ev_x_cur)
100     ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO);
101 root 1.10 else
102 root 1.37 ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO);
103 root 1.9 #else
104 root 1.39 assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY", !ev_x_cur));
105 root 1.10
106 root 1.37 ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO);
107 root 1.9 #endif
108 root 1.1
109 root 1.37 return ev_x_cur;
110 root 1.1 }
111    
112     void event_base_free (struct event_base *base)
113     {
114 root 1.8 dLOOPbase;
115    
116 root 1.9 #if EV_MULTIPLICITY
117 root 1.29 if (ev_default_loop (EVFLAG_AUTO) != loop)
118 root 1.13 ev_loop_destroy (loop);
119 root 1.9 #endif
120 root 1.1 }
121    
122     int event_dispatch (void)
123     {
124 root 1.37 return event_base_dispatch (ev_x_cur);
125 root 1.1 }
126    
127 root 1.12 #ifdef EV_STANDALONE
128 root 1.1 void event_set_log_callback (event_log_cb cb)
129     {
130     /* nop */
131     }
132 root 1.5 #endif
133 root 1.1
134     int event_loop (int flags)
135     {
136 root 1.37 return event_base_loop (ev_x_cur, flags);
137 root 1.1 }
138    
139     int event_loopexit (struct timeval *tv)
140     {
141 root 1.37 return event_base_loopexit (ev_x_cur, tv);
142 root 1.1 }
143    
144     static void
145 root 1.37 ev_x_cb (struct event *ev, int revents)
146 root 1.1 {
147     revents &= EV_READ | EV_WRITE | EV_TIMEOUT | EV_SIGNAL;
148    
149     ev->ev_res = revents;
150 root 1.26 ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);
151 root 1.1 }
152    
153     static void
154 root 1.37 ev_x_cb_sig (EV_P_ struct ev_signal *w, int revents)
155 root 1.1 {
156 root 1.20 struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig));
157    
158     if (revents & EV_ERROR)
159     event_del (ev);
160    
161 root 1.37 ev_x_cb (ev, revents);
162 root 1.1 }
163    
164     static void
165 root 1.37 ev_x_cb_io (EV_P_ struct ev_io *w, int revents)
166 root 1.1 {
167 root 1.7 struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));
168    
169 root 1.32 if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST))
170 root 1.20 event_del (ev);
171 root 1.7
172 root 1.37 ev_x_cb (ev, revents);
173 root 1.1 }
174    
175     static void
176 root 1.37 ev_x_cb_to (EV_P_ struct ev_timer *w, int revents)
177 root 1.1 {
178 root 1.14 struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to));
179    
180     event_del (ev);
181    
182 root 1.37 ev_x_cb (ev, revents);
183 root 1.1 }
184    
185     void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)
186     {
187 root 1.14 if (events & EV_SIGNAL)
188 root 1.37 ev_init (&ev->iosig.sig, ev_x_cb_sig);
189 root 1.14 else
190 root 1.37 ev_init (&ev->iosig.io, ev_x_cb_io);
191 root 1.4
192 root 1.37 ev_init (&ev->to, ev_x_cb_to);
193 root 1.1
194 root 1.37 ev->ev_base = ev_x_cur; /* not threadsafe, but it's how libevent works */
195 root 1.1 ev->ev_fd = fd;
196     ev->ev_events = events;
197     ev->ev_pri = 0;
198     ev->ev_callback = cb;
199     ev->ev_arg = arg;
200     ev->ev_res = 0;
201 root 1.27 ev->ev_flags = EVLIST_INIT;
202 root 1.1 }
203    
204     int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
205     {
206 root 1.37 return event_base_once (ev_x_cur, fd, events, cb, arg, tv);
207 root 1.1 }
208    
209     int event_add (struct event *ev, struct timeval *tv)
210     {
211 root 1.7 dLOOPev;
212    
213 root 1.4 if (ev->ev_events & EV_SIGNAL)
214 root 1.1 {
215 root 1.31 if (!ev_is_active (&ev->iosig.sig))
216     {
217     ev_signal_set (&ev->iosig.sig, ev->ev_fd);
218     ev_signal_start (EV_A_ &ev->iosig.sig);
219 root 1.27
220 root 1.31 ev->ev_flags |= EVLIST_SIGNAL;
221     }
222 root 1.1 }
223 root 1.4 else if (ev->ev_events & (EV_READ | EV_WRITE))
224 root 1.1 {
225 root 1.31 if (!ev_is_active (&ev->iosig.io))
226     {
227     ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE));
228     ev_io_start (EV_A_ &ev->iosig.io);
229 root 1.27
230 root 1.31 ev->ev_flags |= EVLIST_INSERTED;
231     }
232 root 1.1 }
233    
234 root 1.4 if (tv)
235 root 1.1 {
236 root 1.37 ev->to.repeat = ev_tv_get (tv);
237 root 1.31 ev_timer_again (EV_A_ &ev->to);
238 root 1.27 ev->ev_flags |= EVLIST_TIMEOUT;
239 root 1.1 }
240 root 1.31 else
241 root 1.32 {
242 root 1.31 ev_timer_stop (EV_A_ &ev->to);
243 root 1.32 ev->ev_flags &= ~EVLIST_TIMEOUT;
244     }
245 root 1.1
246 root 1.27 ev->ev_flags |= EVLIST_ACTIVE;
247    
248 root 1.1 return 0;
249     }
250    
251     int event_del (struct event *ev)
252     {
253 root 1.7 dLOOPev;
254    
255 root 1.4 if (ev->ev_events & EV_SIGNAL)
256 root 1.32 ev_signal_stop (EV_A_ &ev->iosig.sig);
257 root 1.16 else if (ev->ev_events & (EV_READ | EV_WRITE))
258 root 1.32 ev_io_stop (EV_A_ &ev->iosig.io);
259 root 1.1
260     if (ev_is_active (&ev->to))
261 root 1.7 ev_timer_stop (EV_A_ &ev->to);
262 root 1.1
263 root 1.27 ev->ev_flags = EVLIST_INIT;
264    
265 root 1.1 return 0;
266     }
267    
268 root 1.21 void event_active (struct event *ev, int res, short ncalls)
269     {
270 root 1.23 dLOOPev;
271    
272 root 1.21 if (res & EV_TIMEOUT)
273 root 1.23 ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT);
274 root 1.21
275     if (res & EV_SIGNAL)
276 root 1.23 ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL);
277 root 1.21
278     if (res & (EV_READ | EV_WRITE))
279 root 1.23 ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE));
280 root 1.21 }
281    
282 root 1.1 int event_pending (struct event *ev, short events, struct timeval *tv)
283     {
284 root 1.18 short revents = 0;
285 root 1.7 dLOOPev;
286    
287 root 1.4 if (ev->ev_events & EV_SIGNAL)
288     {
289     /* sig */
290 root 1.14 if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig))
291 root 1.4 revents |= EV_SIGNAL;
292     }
293 root 1.16 else if (ev->ev_events & (EV_READ | EV_WRITE))
294 root 1.4 {
295     /* io */
296 root 1.14 if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io))
297 root 1.4 revents |= ev->ev_events & (EV_READ | EV_WRITE);
298     }
299 root 1.1
300 root 1.14 if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to))
301 root 1.1 {
302     revents |= EV_TIMEOUT;
303    
304     if (tv)
305 root 1.37 ev_tv_set (tv, ev_now (EV_A)); /* not sure if this is right :) */
306 root 1.1 }
307    
308     return events & revents;
309     }
310    
311     int event_priority_init (int npri)
312     {
313 root 1.37 return event_base_priority_init (ev_x_cur, npri);
314 root 1.1 }
315    
316     int event_priority_set (struct event *ev, int pri)
317     {
318     ev->ev_pri = pri;
319    
320     return 0;
321     }
322    
323     int event_base_set (struct event_base *base, struct event *ev)
324     {
325     ev->ev_base = base;
326    
327     return 0;
328     }
329    
330     int event_base_loop (struct event_base *base, int flags)
331     {
332 root 1.7 dLOOPbase;
333 root 1.8
334     ev_loop (EV_A_ flags);
335 root 1.1
336     return 0;
337     }
338    
339     int event_base_dispatch (struct event_base *base)
340     {
341     return event_base_loop (base, 0);
342     }
343    
344     static void
345 root 1.37 ev_x_loopexit_cb (int revents, void *base)
346 root 1.1 {
347 root 1.9 dLOOPbase;
348    
349 root 1.30 ev_unloop (EV_A_ EVUNLOOP_ONE);
350 root 1.1 }
351    
352     int event_base_loopexit (struct event_base *base, struct timeval *tv)
353     {
354 root 1.37 ev_tstamp after = ev_tv_get (tv);
355 root 1.7 dLOOPbase;
356 root 1.1
357 root 1.37 ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base);
358 root 1.5
359 root 1.34 return 0;
360 root 1.1 }
361    
362 root 1.37 struct ev_x_once
363 root 1.1 {
364     int fd;
365     void (*cb)(int, short, void *);
366     void *arg;
367     };
368    
369     static void
370 root 1.37 ev_x_once_cb (int revents, void *arg)
371 root 1.1 {
372 root 1.37 struct ev_x_once *once = (struct ev_x_once *)arg;
373 root 1.1
374 root 1.26 once->cb (once->fd, (short)revents, once->arg);
375 root 1.1 free (once);
376     }
377    
378     int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
379     {
380 root 1.37 struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once));
381 root 1.7 dLOOPbase;
382 root 1.1
383     if (!once)
384     return -1;
385    
386     once->fd = fd;
387     once->cb = cb;
388     once->arg = arg;
389    
390 root 1.37 ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once);
391 root 1.1
392     return 0;
393     }
394    
395     int event_base_priority_init (struct event_base *base, int npri)
396     {
397 root 1.13 /*dLOOPbase;*/
398 root 1.7
399 root 1.1 return 0;
400     }
401