]> git.llucax.com Git - software/libev.git/blob - ev++.h
aa90c37c996a7a0a87df664d88c516d994f52d21
[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 namespace ev {
50
51   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   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 #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   template<class ev_watcher, class watcher>
398   struct base : ev_watcher
399   {
400     #if EV_MULTIPLICITY
401       EV_PX;
402
403       void set (EV_PX)
404       {
405         this->EV_A = EV_A;
406       }
407     #endif
408
409     base (EV_PX)
410     #if EV_MULTIPLICITY
411       : EV_A (EV_A)
412     #endif
413     {
414       ev_init (this, 0);
415     }
416
417     void set_ (void *data, void (*cb)(EV_P_ ev_watcher *w, int revents))
418     {
419       this->data = data;
420       ev_set_cb (static_cast<ev_watcher *>(this), cb);
421     }
422
423     // method callback
424     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     static void method_thunk (EV_P_ ev_watcher *w, int revents)
432     {
433       K *obj = static_cast<K *>(w->data);
434       (obj->*method) (*static_cast<watcher *>(w), revents);
435     }
436
437     // const method callback
438     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     static void const_method_thunk (EV_P_ ev_watcher *w, int revents)
446     {
447       K *obj = static_cast<K *>(w->data);
448       (static_cast<K *>(w->data)->*method) (*static_cast<watcher *>(w), revents);
449     }
450
451     // function callback
452     template<void (*function)(watcher &w, int)>
453     void set (void *data = 0)
454     {
455       set_ (data, function_thunk<function>);
456     }
457
458     template<void (*function)(watcher &w, int)>
459     static void function_thunk (EV_P_ ev_watcher *w, int revents)
460     {
461       function (*static_cast<watcher *>(w), revents);
462     }
463
464     // 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     void operator ()(int events = EV_UNDEF)
479     {
480       return ev_cb (static_cast<ev_watcher *>(this))
481         (static_cast<ev_watcher *>(this), events);
482     }
483
484     bool is_active () const
485     {
486       return ev_is_active (static_cast<const ev_watcher *>(this));
487     }
488
489     bool is_pending () const
490     {
491       return ev_is_pending (static_cast<const ev_watcher *>(this));
492     }
493
494     void feed_event (int revents)
495     {
496       ev_feed_event (EV_A_ static_cast<const ev_watcher *>(this), revents);
497     }
498   };
499
500   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   #if EV_MULTIPLICITY
541     #define EV_CONSTRUCT(cppstem,cstem)                                                 \
542       (EV_PX = get_default_loop ())                                                     \
543         : base<ev_ ## cstem, cppstem> (EV_A)                                            \
544       {                                                                                 \
545       }
546   #else
547     #define EV_CONSTRUCT(cppstem,cstem)                                                 \
548       ()                                                                                \
549       {                                                                                 \
550       }
551   #endif
552
553   /* using a template here would require quite a bit more lines,
554    * so a macro solution was chosen */
555   #define EV_BEGIN_WATCHER(cppstem,cstem)                                               \
556                                                                                         \
557   struct cppstem : base<ev_ ## cstem, cppstem>                                          \
558   {                                                                                     \
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     cppstem EV_CONSTRUCT(cppstem,cstem)                                                 \
570                                                                                         \
571     ~cppstem ()                                                                         \
572     {                                                                                   \
573       stop ();                                                                          \
574     }                                                                                   \
575                                                                                         \
576     using base<ev_ ## cstem, cppstem>::set;                                             \
577                                                                                         \
578   private:                                                                              \
579                                                                                         \
580     cppstem (const cppstem &o);                                                         \
581                                                                                         \
582     cppstem & operator =(const cppstem &o);                                             \
583                                                                                         \
584   public:
585
586   #define EV_END_WATCHER(cppstem,cstem)                                                 \
587   };
588
589   EV_BEGIN_WATCHER (io, io)
590     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   EV_END_WATCHER (io, io)
612
613   EV_BEGIN_WATCHER (timer, timer)
614     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   EV_END_WATCHER (timer, timer)
633
634   #if EV_PERIODIC_ENABLE
635   EV_BEGIN_WATCHER (periodic, periodic)
636     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   EV_END_WATCHER (periodic, periodic)
655   #endif
656
657   EV_BEGIN_WATCHER (sig, signal)
658     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   EV_END_WATCHER (sig, signal)
672
673   EV_BEGIN_WATCHER (child, child)
674     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   EV_END_WATCHER (child, child)
688
689   #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       stop ();
702       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
717   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   EV_BEGIN_WATCHER (embed, embed)
727     void start (struct ev_loop *embedded_loop)
728     {
729       stop ();
730       ev_embed_set (static_cast<ev_embed *>(this), embedded_loop);
731       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   #if EV_FORK_ENABLE
742   EV_BEGIN_WATCHER (fork, fork)
743     void set () { }
744   EV_END_WATCHER (fork, fork)
745   #endif
746
747   #undef EV_PX
748   #undef EV_PX_
749   #undef EV_CONSTRUCT
750   #undef EV_BEGIN_WATCHER
751   #undef EV_END_WATCHER
752
753 }
754
755 #endif
756