ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/event.c
Revision: 1.35
Committed: Fri May 2 07:35:47 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-3_33, rel-3_4
Changes since 1.34: +0 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 /*
2     * libevent compatibility layer
3     *
4     * Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
5     * 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.18 #ifndef WIN32
45     # include <sys/time.h>
46     #endif
47    
48 root 1.24 #ifdef EV_EVENT_H
49     # include EV_EVENT_H
50     #else
51     # include "event.h"
52     #endif
53 root 1.1
54 root 1.9 #if EV_MULTIPLICITY
55     # define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base
56     # define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base
57 root 1.8 #else
58     # define dLOOPev
59     # define dLOOPbase
60     #endif
61 root 1.7
62 root 1.9 /* never accessed, will always be cast from/to ev_loop */
63 root 1.1 struct event_base
64     {
65     int dummy;
66     };
67    
68 root 1.10 static struct event_base *x_cur;
69 root 1.1
70     static void
71     tv_set (struct timeval *tv, ev_tstamp at)
72     {
73     tv->tv_sec = (long)at;
74     tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);
75     }
76    
77     static ev_tstamp
78     tv_get (struct timeval *tv)
79     {
80     if (tv)
81     return tv->tv_sec + tv->tv_usec * 1e-6;
82     else
83     return -1.;
84     }
85    
86     #define EVENT_VERSION(a,b) # a "." # b
87    
88     const char *event_get_version (void)
89     {
90     return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);
91     }
92    
93     const char *event_get_method (void)
94     {
95     return "libev";
96     }
97    
98     void *event_init (void)
99     {
100 root 1.9 #if EV_MULTIPLICITY
101 root 1.10 if (x_cur)
102 root 1.28 x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO);
103 root 1.10 else
104 root 1.28 x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO);
105 root 1.9 #else
106 root 1.10 assert (("multiple event bases not supported when not compiled with EV_MULTIPLICITY", !x_cur));
107    
108 root 1.28 x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO);
109 root 1.9 #endif
110 root 1.1
111 root 1.9 return x_cur;
112 root 1.1 }
113    
114     void event_base_free (struct event_base *base)
115     {
116 root 1.8 dLOOPbase;
117    
118 root 1.9 #if EV_MULTIPLICITY
119 root 1.29 if (ev_default_loop (EVFLAG_AUTO) != loop)
120 root 1.13 ev_loop_destroy (loop);
121 root 1.9 #endif
122 root 1.1 }
123    
124     int event_dispatch (void)
125     {
126     return event_base_dispatch (x_cur);
127     }
128    
129 root 1.12 #ifdef EV_STANDALONE
130 root 1.1 void event_set_log_callback (event_log_cb cb)
131     {
132     /* nop */
133     }
134 root 1.5 #endif
135 root 1.1
136     int event_loop (int flags)
137     {
138     return event_base_loop (x_cur, flags);
139     }
140    
141     int event_loopexit (struct timeval *tv)
142     {
143 root 1.5 return event_base_loopexit (x_cur, tv);
144 root 1.1 }
145    
146     static void
147     x_cb (struct event *ev, int revents)
148     {
149     revents &= EV_READ | EV_WRITE | EV_TIMEOUT | EV_SIGNAL;
150    
151     ev->ev_res = revents;
152 root 1.26 ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);
153 root 1.1 }
154    
155     static void
156 root 1.7 x_cb_sig (EV_P_ struct ev_signal *w, int revents)
157 root 1.1 {
158 root 1.20 struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig));
159    
160     if (revents & EV_ERROR)
161     event_del (ev);
162    
163     x_cb (ev, revents);
164 root 1.1 }
165    
166     static void
167 root 1.7 x_cb_io (EV_P_ struct ev_io *w, int revents)
168 root 1.1 {
169 root 1.7 struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));
170    
171 root 1.32 if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST))
172 root 1.20 event_del (ev);
173 root 1.7
174     x_cb (ev, revents);
175 root 1.1 }
176    
177     static void
178 root 1.7 x_cb_to (EV_P_ struct ev_timer *w, int revents)
179 root 1.1 {
180 root 1.14 struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to));
181    
182     event_del (ev);
183    
184     x_cb (ev, revents);
185 root 1.1 }
186    
187     void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)
188     {
189 root 1.14 if (events & EV_SIGNAL)
190 root 1.25 ev_init (&ev->iosig.sig, x_cb_sig);
191 root 1.14 else
192 root 1.25 ev_init (&ev->iosig.io, x_cb_io);
193 root 1.4
194 root 1.25 ev_init (&ev->to, x_cb_to);
195 root 1.1
196 root 1.9 ev->ev_base = x_cur; /* not threadsafe, but its like libevent works */
197 root 1.1 ev->ev_fd = fd;
198     ev->ev_events = events;
199     ev->ev_pri = 0;
200     ev->ev_callback = cb;
201     ev->ev_arg = arg;
202     ev->ev_res = 0;
203 root 1.27 ev->ev_flags = EVLIST_INIT;
204 root 1.1 }
205    
206     int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
207     {
208 root 1.5 return event_base_once (x_cur, fd, events, cb, arg, tv);
209 root 1.1 }
210    
211     int event_add (struct event *ev, struct timeval *tv)
212     {
213 root 1.7 dLOOPev;
214    
215 root 1.4 if (ev->ev_events & EV_SIGNAL)
216 root 1.1 {
217 root 1.31 if (!ev_is_active (&ev->iosig.sig))
218     {
219     ev_signal_set (&ev->iosig.sig, ev->ev_fd);
220     ev_signal_start (EV_A_ &ev->iosig.sig);
221 root 1.27
222 root 1.31 ev->ev_flags |= EVLIST_SIGNAL;
223     }
224 root 1.1 }
225 root 1.4 else if (ev->ev_events & (EV_READ | EV_WRITE))
226 root 1.1 {
227 root 1.31 if (!ev_is_active (&ev->iosig.io))
228     {
229     ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE));
230     ev_io_start (EV_A_ &ev->iosig.io);
231 root 1.27
232 root 1.31 ev->ev_flags |= EVLIST_INSERTED;
233     }
234 root 1.1 }
235    
236 root 1.4 if (tv)
237 root 1.1 {
238 root 1.31 ev->to.repeat = tv_get (tv);
239     ev_timer_again (EV_A_ &ev->to);
240 root 1.27 ev->ev_flags |= EVLIST_TIMEOUT;
241 root 1.1 }
242 root 1.31 else
243 root 1.32 {
244 root 1.31 ev_timer_stop (EV_A_ &ev->to);
245 root 1.32 ev->ev_flags &= ~EVLIST_TIMEOUT;
246     }
247 root 1.1
248 root 1.27 ev->ev_flags |= EVLIST_ACTIVE;
249    
250 root 1.1 return 0;
251     }
252    
253     int event_del (struct event *ev)
254     {
255 root 1.7 dLOOPev;
256    
257 root 1.4 if (ev->ev_events & EV_SIGNAL)
258 root 1.32 ev_signal_stop (EV_A_ &ev->iosig.sig);
259 root 1.16 else if (ev->ev_events & (EV_READ | EV_WRITE))
260 root 1.32 ev_io_stop (EV_A_ &ev->iosig.io);
261 root 1.1
262     if (ev_is_active (&ev->to))
263 root 1.7 ev_timer_stop (EV_A_ &ev->to);
264 root 1.1
265 root 1.27 ev->ev_flags = EVLIST_INIT;
266    
267 root 1.1 return 0;
268     }
269    
270 root 1.21 void event_active (struct event *ev, int res, short ncalls)
271     {
272 root 1.23 dLOOPev;
273    
274 root 1.21 if (res & EV_TIMEOUT)
275 root 1.23 ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT);
276 root 1.21
277     if (res & EV_SIGNAL)
278 root 1.23 ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL);
279 root 1.21
280     if (res & (EV_READ | EV_WRITE))
281 root 1.23 ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE));
282 root 1.21 }
283    
284 root 1.1 int event_pending (struct event *ev, short events, struct timeval *tv)
285     {
286 root 1.18 short revents = 0;
287 root 1.7 dLOOPev;
288    
289 root 1.4 if (ev->ev_events & EV_SIGNAL)
290     {
291     /* sig */
292 root 1.14 if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig))
293 root 1.4 revents |= EV_SIGNAL;
294     }
295 root 1.16 else if (ev->ev_events & (EV_READ | EV_WRITE))
296 root 1.4 {
297     /* io */
298 root 1.14 if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io))
299 root 1.4 revents |= ev->ev_events & (EV_READ | EV_WRITE);
300     }
301 root 1.1
302 root 1.14 if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to))
303 root 1.1 {
304     revents |= EV_TIMEOUT;
305    
306     if (tv)
307 root 1.7 tv_set (tv, ev_now (EV_A)); /* not sure if this is right :) */
308 root 1.1 }
309    
310     return events & revents;
311     }
312    
313     int event_priority_init (int npri)
314     {
315     return event_base_priority_init (x_cur, npri);
316     }
317    
318     int event_priority_set (struct event *ev, int pri)
319     {
320     ev->ev_pri = pri;
321    
322     return 0;
323     }
324    
325     int event_base_set (struct event_base *base, struct event *ev)
326     {
327     ev->ev_base = base;
328    
329     return 0;
330     }
331    
332     int event_base_loop (struct event_base *base, int flags)
333     {
334 root 1.7 dLOOPbase;
335 root 1.8
336     ev_loop (EV_A_ flags);
337 root 1.1
338     return 0;
339     }
340    
341     int event_base_dispatch (struct event_base *base)
342     {
343     return event_base_loop (base, 0);
344     }
345    
346     static void
347 root 1.9 x_loopexit_cb (int revents, void *base)
348 root 1.1 {
349 root 1.9 dLOOPbase;
350    
351 root 1.30 ev_unloop (EV_A_ EVUNLOOP_ONE);
352 root 1.1 }
353    
354     int event_base_loopexit (struct event_base *base, struct timeval *tv)
355     {
356 root 1.18 ev_tstamp after = tv_get (tv);
357 root 1.7 dLOOPbase;
358 root 1.1
359 root 1.7 ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., x_loopexit_cb, (void *)base);
360 root 1.5
361 root 1.34 return 0;
362 root 1.1 }
363    
364     struct x_once
365     {
366     int fd;
367     void (*cb)(int, short, void *);
368     void *arg;
369     };
370    
371     static void
372     x_once_cb (int revents, void *arg)
373     {
374 root 1.19 struct x_once *once = (struct x_once *)arg;
375 root 1.1
376 root 1.26 once->cb (once->fd, (short)revents, once->arg);
377 root 1.1 free (once);
378     }
379    
380     int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
381     {
382 root 1.19 struct x_once *once = (struct x_once *)malloc (sizeof (struct x_once));
383 root 1.7 dLOOPbase;
384 root 1.1
385     if (!once)
386     return -1;
387    
388     once->fd = fd;
389     once->cb = cb;
390     once->arg = arg;
391    
392 root 1.7 ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), tv_get (tv), x_once_cb, (void *)once);
393 root 1.1
394     return 0;
395     }
396    
397     int event_base_priority_init (struct event_base *base, int npri)
398     {
399 root 1.13 /*dLOOPbase;*/
400 root 1.7
401 root 1.1 return 0;
402     }
403