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