ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev++.h
Revision: 1.28
Committed: Fri Jan 18 18:14:41 2008 UTC (16 years, 3 months ago) by llucax
Content type: text/plain
Branch: MAIN
Changes since 1.27: +315 -14 lines
Log Message:
Add loop wrappers to C++ interface.

3 new classes are provided: loop_ref, dynamic_loop and default_loop.

loop_ref has value semantics and is just a pointer wrapper (but with
reference syntax). You can change a ev_loop* for a loop_ref and
vice-versa without notice. You can create (or asign) a loop_ref from
a ev_loop* and you can cast a loop_ref to a ev_loop*. You can check
for equality between loop_refs and ev_loop pointers. No clean-up is done
by a loop_ref.

dynamic_loop and default_loop have both reference semantics (they are
non-copiable and non-assignable), and provide automatic destruction.

File Contents

# User Rev Content
1 root 1.21 /*
2     * libev simple C++ wrapper classes
3     *
4     * Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
5     * All rights reserved.
6     *
7     * 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     *
28     * 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     */
39    
40 root 1.1 #ifndef EVPP_H__
41     #define EVPP_H__
42    
43 root 1.20 #ifdef EV_H
44     # include EV_H
45     #else
46 root 1.22 # include "ev.h"
47 root 1.20 #endif
48 root 1.1
49     namespace ev {
50    
51 llucax 1.24 typedef ev_tstamp tstamp;
52    
53     enum {
54     UNDEF = EV_UNDEF,
55     NONE = EV_NONE,
56     READ = EV_READ,
57     WRITE = EV_WRITE,
58     TIMEOUT = EV_TIMEOUT,
59     PERIODIC = EV_PERIODIC,
60     SIGNAL = EV_SIGNAL,
61     CHILD = EV_CHILD,
62     STAT = EV_STAT,
63     IDLE = EV_IDLE,
64     CHECK = EV_CHECK,
65     PREPARE = EV_PREPARE,
66     FORK = EV_FORK,
67     EMBED = EV_EMBED,
68     ERROR = EV_ERROR,
69     };
70    
71 llucax 1.25 enum
72     {
73     AUTO = EVFLAG_AUTO,
74     NOENV = EVFLAG_NOENV,
75     FORKCHECK = EVFLAG_FORKCHECK,
76     SELECT = EVBACKEND_SELECT,
77     POLL = EVBACKEND_POLL,
78     EPOLL = EVBACKEND_EPOLL,
79     KQUEUE = EVBACKEND_KQUEUE,
80     DEVPOLL = EVBACKEND_DEVPOLL,
81     PORT = EVBACKEND_PORT
82     };
83    
84     enum
85     {
86     NONBLOCK = EVLOOP_NONBLOCK,
87     ONESHOT = EVLOOP_ONESHOT
88     };
89    
90     enum how_t
91     {
92     ONE = EVUNLOOP_ONE,
93     ALL = EVUNLOOP_ALL
94     };
95    
96 llucax 1.28 #ifdef EV_AX
97     # undef EV_AX
98     #endif
99    
100     #ifdef EV_AX_
101     # undef EV_AX_
102     #endif
103    
104     #if EV_MULTIPLICITY
105     # define EV_AX raw_loop
106     # define EV_AX_ raw_loop,
107     #else
108     # define EV_AX
109     # define EV_AX_
110     #endif
111    
112     struct loop_ref
113     {
114    
115     loop_ref (EV_P)
116     #if EV_MULTIPLICITY
117     : EV_AX (EV_A)
118     #endif
119     {
120     }
121    
122     bool operator== (const loop_ref &other) const
123     {
124     #if EV_MULTIPLICITY
125     return this->EV_AX == other.EV_AX;
126     #else
127     return true;
128     #endif
129     }
130    
131     bool operator!= (const loop_ref &other) const
132     {
133     #if EV_MULTIPLICITY
134     return ! (*this == other);
135     #else
136     return false;
137     #endif
138     }
139    
140     #if EV_MULTIPLICITY
141     bool operator== (struct ev_loop *other) const
142     {
143     return this->EV_AX == other;
144     }
145    
146     bool operator!= (struct ev_loop *other) const
147     {
148     return ! (*this == other);
149     }
150    
151     bool operator== (const struct ev_loop *other) const
152     {
153     return this->EV_AX == other;
154     }
155    
156     bool operator!= (const struct ev_loop *other) const
157     {
158     return (*this == other);
159     }
160    
161     operator struct ev_loop * () const
162     {
163     return EV_AX;
164     }
165    
166     operator const struct ev_loop * () const
167     {
168     return EV_AX;
169     }
170    
171     bool is_default () const
172     {
173     return EV_AX == ev_default_loop (0);
174     }
175     #endif
176    
177     void loop (int flags = 0)
178     {
179     ev_loop (EV_AX_ flags);
180     }
181    
182     void unloop (how_t how = ONE)
183     {
184     ev_unloop (EV_AX_ how);
185     }
186    
187     void post_fork ()
188     {
189     #if EV_MULTIPLICITY
190     ev_loop_fork (EV_AX);
191     #else
192     ev_default_fork ();
193     #endif
194     }
195    
196     unsigned int count () const
197     {
198     return ev_loop_count (EV_AX);
199     }
200    
201     unsigned int backend () const
202     {
203     return ev_backend (EV_AX);
204     }
205    
206     tstamp now () const
207     {
208     return ev_now (EV_AX);
209     }
210    
211     void ref ()
212     {
213     ev_ref (EV_AX);
214     }
215    
216     void unref ()
217     {
218     ev_unref (EV_AX);
219     }
220    
221     void set_io_collect_interval (tstamp interval)
222     {
223     ev_set_io_collect_interval (EV_AX_ interval);
224     }
225    
226     void set_timeout_collect_interval (tstamp interval)
227     {
228     ev_set_timeout_collect_interval (EV_AX_ interval);
229     }
230    
231     // function callback
232     void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void* arg = 0)
233     {
234     ev_once (EV_AX_ fd, events, timeout, cb, arg);
235     }
236    
237     // method callback
238     template<class K, void (K::*method)(int)>
239     void once (int fd, int events, tstamp timeout, K *object)
240     {
241     once (fd, events, timeout, method_thunk<K, method>, object);
242     }
243    
244     template<class K, void (K::*method)(int)>
245     static void method_thunk (int revents, void* arg)
246     {
247     K *obj = static_cast<K *>(arg);
248     (obj->*method) (revents);
249     }
250    
251     // const method callback
252     template<class K, void (K::*method)(int) const>
253     void once (int fd, int events, tstamp timeout, const K *object)
254     {
255     once (fd, events, timeout, const_method_thunk<K, method>, object);
256     }
257    
258     template<class K, void (K::*method)(int) const>
259     static void const_method_thunk (int revents, void* arg)
260     {
261     K *obj = static_cast<K *>(arg);
262     (obj->*method) (revents);
263     }
264    
265     // simple method callback
266     template<class K, void (K::*method)()>
267     void once (int fd, int events, tstamp timeout, K *object)
268     {
269     once (fd, events, timeout, method_noargs_thunk<K, method>, object);
270     }
271    
272     template<class K, void (K::*method)()>
273     static void method_noargs_thunk (int revents, void* arg)
274     {
275     K *obj = static_cast<K *>(arg);
276     (obj->*method) ();
277     }
278    
279     // simpler function callback
280     template<void (*cb)(int)>
281     void once (int fd, int events, tstamp timeout)
282     {
283     once (fd, events, timeout, simpler_func_thunk<cb>);
284     }
285    
286     template<void (*cb)(int)>
287     static void simpler_func_thunk (int revents, void* arg)
288     {
289     (*cb) (revents);
290     }
291    
292     // simplest function callback
293     template<void (*cb)()>
294     void once (int fd, int events, tstamp timeout)
295     {
296     once (fd, events, timeout, simplest_func_thunk<cb>);
297     }
298    
299     template<void (*cb)()>
300     static void simplest_func_thunk (int revents, void* arg)
301     {
302     (*cb) ();
303     }
304    
305     void feed_fd_event (int fd, int revents)
306     {
307     ev_feed_fd_event (EV_AX_ fd, revents);
308     }
309    
310     void feed_signal_event (int signum)
311     {
312     ev_feed_signal_event (EV_AX_ signum);
313     }
314    
315     #if EV_MULTIPLICITY
316     struct ev_loop* EV_AX;
317     #endif
318    
319     };
320    
321     #if EV_MULTIPLICITY
322     struct dynamic_loop: loop_ref
323     {
324    
325     dynamic_loop (unsigned int flags = AUTO)
326     : loop_ref (ev_loop_new (flags))
327     {
328     }
329    
330     ~dynamic_loop ()
331     {
332     ev_loop_destroy (EV_AX);
333     EV_AX = 0;
334     }
335    
336     private:
337    
338     dynamic_loop (const dynamic_loop &);
339    
340     dynamic_loop & operator= (const dynamic_loop &);
341    
342     };
343     #endif
344    
345     struct default_loop: loop_ref
346     {
347    
348     default_loop (unsigned int flags = AUTO)
349     #if EV_MULTIPLICITY
350     : loop_ref (ev_default_loop (flags))
351     {
352     }
353     #else
354     {
355     ev_default_loop (flags);
356     }
357     #endif
358    
359     ~default_loop ()
360     {
361     ev_default_destroy ();
362     #if EV_MULTIPLICITY
363     EV_AX = 0;
364     #endif
365     }
366    
367     private:
368    
369     default_loop (const default_loop &);
370    
371     default_loop & operator= (const default_loop &);
372    
373     };
374    
375     inline loop_ref get_default_loop ()
376     {
377     #if EV_MULTIPLICITY
378     return ev_default_loop (0);
379     #else
380     return loop_ref ();
381     #endif
382     }
383    
384     #undef EV_AX
385     #undef EV_AX_
386    
387     #undef EV_PX
388     #undef EV_PX_
389     #if EV_MULTIPLICITY
390     # define EV_PX loop_ref EV_A
391     # define EV_PX_ loop_ref EV_A_
392     #else
393     # define EV_PX
394     # define EV_PX_
395     #endif
396    
397 root 1.13 template<class ev_watcher, class watcher>
398     struct base : ev_watcher
399 root 1.1 {
400 root 1.13 #if EV_MULTIPLICITY
401 llucax 1.28 EV_PX;
402 root 1.1
403 llucax 1.28 void set (EV_PX)
404 root 1.13 {
405     this->EV_A = EV_A;
406     }
407     #endif
408 root 1.1
409 llucax 1.28 base (EV_PX)
410     #if EV_MULTIPLICITY
411     : EV_A (EV_A)
412     #endif
413 root 1.13 {
414     ev_init (this, 0);
415     }
416    
417 root 1.18 void set_ (void *data, void (*cb)(EV_P_ ev_watcher *w, int revents))
418 root 1.13 {
419 root 1.17 this->data = data;
420 root 1.18 ev_set_cb (static_cast<ev_watcher *>(this), cb);
421 root 1.13 }
422    
423 root 1.19 // method callback
424 root 1.13 template<class K, void (K::*method)(watcher &w, int)>
425     void set (K *object)
426     {
427     set_ (object, method_thunk<K, method>);
428     }
429    
430     template<class K, void (K::*method)(watcher &w, int)>
431 root 1.18 static void method_thunk (EV_P_ ev_watcher *w, int revents)
432 root 1.13 {
433 root 1.17 K *obj = static_cast<K *>(w->data);
434 root 1.18 (obj->*method) (*static_cast<watcher *>(w), revents);
435 root 1.13 }
436    
437 root 1.19 // const method callback
438 root 1.13 template<class K, void (K::*method)(watcher &w, int) const>
439     void set (const K *object)
440     {
441     set_ (object, const_method_thunk<K, method>);
442     }
443    
444     template<class K, void (K::*method)(watcher &w, int) const>
445 root 1.18 static void const_method_thunk (EV_P_ ev_watcher *w, int revents)
446 root 1.13 {
447 root 1.17 K *obj = static_cast<K *>(w->data);
448 root 1.18 (static_cast<K *>(w->data)->*method) (*static_cast<watcher *>(w), revents);
449 root 1.13 }
450    
451 root 1.19 // function callback
452 root 1.17 template<void (*function)(watcher &w, int)>
453     void set (void *data = 0)
454 root 1.13 {
455 root 1.16 set_ (data, function_thunk<function>);
456 root 1.13 }
457    
458     template<void (*function)(watcher &w, int)>
459 root 1.18 static void function_thunk (EV_P_ ev_watcher *w, int revents)
460 root 1.13 {
461 root 1.18 function (*static_cast<watcher *>(w), revents);
462 root 1.13 }
463    
464 root 1.19 // simple callback
465     template<class K, void (K::*method)()>
466     void set (K *object)
467     {
468     set_ (object, method_noargs_thunk<K, method>);
469     }
470    
471     template<class K, void (K::*method)()>
472     static void method_noargs_thunk (EV_P_ ev_watcher *w, int revents)
473     {
474     K *obj = static_cast<K *>(w->data);
475     (obj->*method) ();
476     }
477    
478 root 1.13 void operator ()(int events = EV_UNDEF)
479     {
480 root 1.14 return ev_cb (static_cast<ev_watcher *>(this))
481     (static_cast<ev_watcher *>(this), events);
482 root 1.13 }
483    
484     bool is_active () const
485 root 1.1 {
486 root 1.13 return ev_is_active (static_cast<const ev_watcher *>(this));
487 root 1.1 }
488    
489 root 1.13 bool is_pending () const
490 root 1.1 {
491 root 1.13 return ev_is_pending (static_cast<const ev_watcher *>(this));
492 root 1.1 }
493 llucax 1.27
494     void feed_event (int revents)
495     {
496     ev_feed_event (EV_A_ static_cast<const ev_watcher *>(this), revents);
497     }
498 root 1.1 };
499    
500 llucax 1.26 inline void delay (tstamp interval)
501     {
502     ev_sleep (interval);
503     }
504    
505     inline int version_major ()
506     {
507     return ev_version_major ();
508     }
509    
510     inline int version_minor ()
511     {
512     return ev_version_minor ();
513     }
514    
515     inline unsigned int supported_backends ()
516     {
517     return ev_supported_backends ();
518     }
519    
520     inline unsigned int recommended_backends ()
521     {
522     return ev_recommended_backends ();
523     }
524    
525     inline unsigned int embeddable_backends ()
526     {
527     return ev_embeddable_backends ();
528     }
529    
530     inline void set_allocator (void *(*cb)(void *ptr, long size))
531     {
532     ev_set_allocator (cb);
533     }
534    
535     inline void set_syserr_cb (void (*cb)(const char *msg))
536     {
537     ev_set_syserr_cb (cb);
538     }
539    
540 root 1.1 #if EV_MULTIPLICITY
541 llucax 1.28 #define EV_CONSTRUCT(cppstem,cstem) \
542     (EV_PX = get_default_loop ()) \
543     : base<ev_ ## cstem, cppstem> (EV_A) \
544 root 1.1 { \
545 root 1.13 }
546 root 1.1 #else
547 llucax 1.28 #define EV_CONSTRUCT(cppstem,cstem) \
548 root 1.13 () \
549     { \
550     }
551 root 1.1 #endif
552    
553     /* using a template here would require quite a bit more lines,
554     * so a macro solution was chosen */
555 root 1.4 #define EV_BEGIN_WATCHER(cppstem,cstem) \
556 root 1.1 \
557 root 1.13 struct cppstem : base<ev_ ## cstem, cppstem> \
558 root 1.1 { \
559     void start () \
560     { \
561     ev_ ## cstem ## _start (EV_A_ static_cast<ev_ ## cstem *>(this)); \
562     } \
563     \
564     void stop () \
565     { \
566     ev_ ## cstem ## _stop (EV_A_ static_cast<ev_ ## cstem *>(this)); \
567     } \
568     \
569 llucax 1.28 cppstem EV_CONSTRUCT(cppstem,cstem) \
570 root 1.1 \
571 root 1.3 ~cppstem () \
572     { \
573     stop (); \
574     } \
575     \
576 root 1.13 using base<ev_ ## cstem, cppstem>::set; \
577     \
578 root 1.1 private: \
579     \
580 llucax 1.23 cppstem (const cppstem &o); \
581 root 1.6 \
582 llucax 1.23 cppstem & operator =(const cppstem &o); \
583 root 1.1 \
584     public:
585    
586 root 1.4 #define EV_END_WATCHER(cppstem,cstem) \
587 root 1.6 };
588 root 1.4
589     EV_BEGIN_WATCHER (io, io)
590 root 1.1 void set (int fd, int events)
591     {
592     int active = is_active ();
593     if (active) stop ();
594     ev_io_set (static_cast<ev_io *>(this), fd, events);
595     if (active) start ();
596     }
597    
598     void set (int events)
599     {
600     int active = is_active ();
601     if (active) stop ();
602     ev_io_set (static_cast<ev_io *>(this), fd, events);
603     if (active) start ();
604     }
605    
606     void start (int fd, int events)
607     {
608     set (fd, events);
609     start ();
610     }
611 root 1.4 EV_END_WATCHER (io, io)
612 root 1.1
613 root 1.4 EV_BEGIN_WATCHER (timer, timer)
614 root 1.1 void set (ev_tstamp after, ev_tstamp repeat = 0.)
615     {
616     int active = is_active ();
617     if (active) stop ();
618     ev_timer_set (static_cast<ev_timer *>(this), after, repeat);
619     if (active) start ();
620     }
621    
622     void start (ev_tstamp after, ev_tstamp repeat = 0.)
623     {
624     set (after, repeat);
625     start ();
626     }
627    
628     void again ()
629     {
630     ev_timer_again (EV_A_ static_cast<ev_timer *>(this));
631     }
632 root 1.4 EV_END_WATCHER (timer, timer)
633 root 1.1
634 root 1.8 #if EV_PERIODIC_ENABLE
635 root 1.4 EV_BEGIN_WATCHER (periodic, periodic)
636 root 1.1 void set (ev_tstamp at, ev_tstamp interval = 0.)
637     {
638     int active = is_active ();
639     if (active) stop ();
640     ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0);
641     if (active) start ();
642     }
643    
644     void start (ev_tstamp at, ev_tstamp interval = 0.)
645     {
646     set (at, interval);
647     start ();
648     }
649    
650     void again ()
651     {
652     ev_periodic_again (EV_A_ static_cast<ev_periodic *>(this));
653     }
654 root 1.4 EV_END_WATCHER (periodic, periodic)
655 root 1.3 #endif
656 root 1.1
657 root 1.4 EV_BEGIN_WATCHER (sig, signal)
658 root 1.1 void set (int signum)
659     {
660     int active = is_active ();
661     if (active) stop ();
662     ev_signal_set (static_cast<ev_signal *>(this), signum);
663     if (active) start ();
664     }
665    
666     void start (int signum)
667     {
668     set (signum);
669     start ();
670     }
671 root 1.4 EV_END_WATCHER (sig, signal)
672 root 1.1
673 root 1.4 EV_BEGIN_WATCHER (child, child)
674 root 1.1 void set (int pid)
675     {
676     int active = is_active ();
677     if (active) stop ();
678     ev_child_set (static_cast<ev_child *>(this), pid);
679     if (active) start ();
680     }
681    
682     void start (int pid)
683     {
684     set (pid);
685     start ();
686     }
687 root 1.4 EV_END_WATCHER (child, child)
688 root 1.1
689 root 1.8 #if EV_STAT_ENABLE
690     EV_BEGIN_WATCHER (stat, stat)
691     void set (const char *path, ev_tstamp interval = 0.)
692     {
693     int active = is_active ();
694     if (active) stop ();
695     ev_stat_set (static_cast<ev_stat *>(this), path, interval);
696     if (active) start ();
697     }
698    
699     void start (const char *path, ev_tstamp interval = 0.)
700     {
701 root 1.12 stop ();
702 root 1.8 set (path, interval);
703     start ();
704     }
705    
706     void update ()
707     {
708     ev_stat_stat (EV_A_ static_cast<ev_stat *>(this));
709     }
710     EV_END_WATCHER (stat, stat)
711     #endif
712    
713     EV_BEGIN_WATCHER (idle, idle)
714     void set () { }
715     EV_END_WATCHER (idle, idle)
716 root 1.7
717 root 1.8 EV_BEGIN_WATCHER (prepare, prepare)
718     void set () { }
719     EV_END_WATCHER (prepare, prepare)
720    
721     EV_BEGIN_WATCHER (check, check)
722     void set () { }
723     EV_END_WATCHER (check, check)
724    
725     #if EV_EMBED_ENABLE
726 root 1.7 EV_BEGIN_WATCHER (embed, embed)
727     void start (struct ev_loop *embedded_loop)
728     {
729 root 1.12 stop ();
730     ev_embed_set (static_cast<ev_embed *>(this), embedded_loop);
731 root 1.7 start ();
732     }
733    
734     void sweep ()
735     {
736     ev_embed_sweep (EV_A_ static_cast<ev_embed *>(this));
737     }
738     EV_END_WATCHER (embed, embed)
739     #endif
740    
741 root 1.10 #if EV_FORK_ENABLE
742     EV_BEGIN_WATCHER (fork, fork)
743     void set () { }
744     EV_END_WATCHER (fork, fork)
745     #endif
746    
747 llucax 1.28 #undef EV_PX
748     #undef EV_PX_
749 root 1.1 #undef EV_CONSTRUCT
750 root 1.4 #undef EV_BEGIN_WATCHER
751 root 1.7 #undef EV_END_WATCHER
752 llucax 1.28
753 root 1.1 }
754    
755     #endif
756