]> git.llucax.com Git - software/libev.git/blob - ev++.h
889603a7168d0509779157c31f1d12b468bbc184
[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 tstamp now ()
501   {
502     return ev_time ();
503   }
504
505   inline void delay (tstamp interval)
506   {
507     ev_sleep (interval);
508   }
509
510   inline int version_major ()
511   {
512     return ev_version_major ();
513   }
514
515   inline int version_minor ()
516   {
517     return ev_version_minor ();
518   }
519
520   inline unsigned int supported_backends ()
521   {
522     return ev_supported_backends ();
523   }
524
525   inline unsigned int recommended_backends ()
526   {
527     return ev_recommended_backends ();
528   }
529
530   inline unsigned int embeddable_backends ()
531   {
532     return ev_embeddable_backends ();
533   }
534
535   inline void set_allocator (void *(*cb)(void *ptr, long size))
536   {
537     ev_set_allocator (cb);
538   }
539
540   inline void set_syserr_cb (void (*cb)(const char *msg))
541   {
542     ev_set_syserr_cb (cb);
543   }
544
545   #if EV_MULTIPLICITY
546     #define EV_CONSTRUCT(cppstem,cstem)                                                 \
547       (EV_PX = get_default_loop ())                                                     \
548         : base<ev_ ## cstem, cppstem> (EV_A)                                            \
549       {                                                                                 \
550       }
551   #else
552     #define EV_CONSTRUCT(cppstem,cstem)                                                 \
553       ()                                                                                \
554       {                                                                                 \
555       }
556   #endif
557
558   /* using a template here would require quite a bit more lines,
559    * so a macro solution was chosen */
560   #define EV_BEGIN_WATCHER(cppstem,cstem)                                               \
561                                                                                         \
562   struct cppstem : base<ev_ ## cstem, cppstem>                                          \
563   {                                                                                     \
564     void start ()                                                                       \
565     {                                                                                   \
566       ev_ ## cstem ## _start (EV_A_ static_cast<ev_ ## cstem *>(this));                 \
567     }                                                                                   \
568                                                                                         \
569     void stop ()                                                                        \
570     {                                                                                   \
571       ev_ ## cstem ## _stop (EV_A_ static_cast<ev_ ## cstem *>(this));                  \
572     }                                                                                   \
573                                                                                         \
574     cppstem EV_CONSTRUCT(cppstem,cstem)                                                 \
575                                                                                         \
576     ~cppstem ()                                                                         \
577     {                                                                                   \
578       stop ();                                                                          \
579     }                                                                                   \
580                                                                                         \
581     using base<ev_ ## cstem, cppstem>::set;                                             \
582                                                                                         \
583   private:                                                                              \
584                                                                                         \
585     cppstem (const cppstem &o);                                                         \
586                                                                                         \
587     cppstem & operator =(const cppstem &o);                                             \
588                                                                                         \
589   public:
590
591   #define EV_END_WATCHER(cppstem,cstem)                                                 \
592   };
593
594   EV_BEGIN_WATCHER (io, io)
595     void set (int fd, int events)
596     {
597       int active = is_active ();
598       if (active) stop ();
599       ev_io_set (static_cast<ev_io *>(this), fd, events);
600       if (active) start ();
601     }
602
603     void set (int events)
604     {
605       int active = is_active ();
606       if (active) stop ();
607       ev_io_set (static_cast<ev_io *>(this), fd, events);
608       if (active) start ();
609     }
610
611     void start (int fd, int events)
612     {
613       set (fd, events);
614       start ();
615     }
616   EV_END_WATCHER (io, io)
617
618   EV_BEGIN_WATCHER (timer, timer)
619     void set (ev_tstamp after, ev_tstamp repeat = 0.)
620     {
621       int active = is_active ();
622       if (active) stop ();
623       ev_timer_set (static_cast<ev_timer *>(this), after, repeat);
624       if (active) start ();
625     }
626
627     void start (ev_tstamp after, ev_tstamp repeat = 0.)
628     {
629       set (after, repeat);
630       start ();
631     }
632
633     void again ()
634     {
635       ev_timer_again (EV_A_ static_cast<ev_timer *>(this));
636     }
637   EV_END_WATCHER (timer, timer)
638
639   #if EV_PERIODIC_ENABLE
640   EV_BEGIN_WATCHER (periodic, periodic)
641     void set (ev_tstamp at, ev_tstamp interval = 0.)
642     {
643       int active = is_active ();
644       if (active) stop ();
645       ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0);
646       if (active) start ();
647     }
648
649     void start (ev_tstamp at, ev_tstamp interval = 0.)
650     {
651       set (at, interval);
652       start ();
653     }
654
655     void again ()
656     {
657       ev_periodic_again (EV_A_ static_cast<ev_periodic *>(this));
658     }
659   EV_END_WATCHER (periodic, periodic)
660   #endif
661
662   EV_BEGIN_WATCHER (sig, signal)
663     void set (int signum)
664     {
665       int active = is_active ();
666       if (active) stop ();
667       ev_signal_set (static_cast<ev_signal *>(this), signum);
668       if (active) start ();
669     }
670
671     void start (int signum)
672     {
673       set (signum);
674       start ();
675     }
676   EV_END_WATCHER (sig, signal)
677
678   EV_BEGIN_WATCHER (child, child)
679     void set (int pid)
680     {
681       int active = is_active ();
682       if (active) stop ();
683       ev_child_set (static_cast<ev_child *>(this), pid);
684       if (active) start ();
685     }
686
687     void start (int pid)
688     {
689       set (pid);
690       start ();
691     }
692   EV_END_WATCHER (child, child)
693
694   #if EV_STAT_ENABLE
695   EV_BEGIN_WATCHER (stat, stat)
696     void set (const char *path, ev_tstamp interval = 0.)
697     {
698       int active = is_active ();
699       if (active) stop ();
700       ev_stat_set (static_cast<ev_stat *>(this), path, interval);
701       if (active) start ();
702     }
703
704     void start (const char *path, ev_tstamp interval = 0.)
705     {
706       stop ();
707       set (path, interval);
708       start ();
709     }
710
711     void update ()
712     {
713       ev_stat_stat (EV_A_ static_cast<ev_stat *>(this));
714     }
715   EV_END_WATCHER (stat, stat)
716   #endif
717
718   EV_BEGIN_WATCHER (idle, idle)
719     void set () { }
720   EV_END_WATCHER (idle, idle)
721
722   EV_BEGIN_WATCHER (prepare, prepare)
723     void set () { }
724   EV_END_WATCHER (prepare, prepare)
725
726   EV_BEGIN_WATCHER (check, check)
727     void set () { }
728   EV_END_WATCHER (check, check)
729
730   #if EV_EMBED_ENABLE
731   EV_BEGIN_WATCHER (embed, embed)
732     void start (struct ev_loop *embedded_loop)
733     {
734       stop ();
735       ev_embed_set (static_cast<ev_embed *>(this), embedded_loop);
736       start ();
737     }
738
739     void sweep ()
740     {
741       ev_embed_sweep (EV_A_ static_cast<ev_embed *>(this));
742     }
743   EV_END_WATCHER (embed, embed)
744   #endif
745
746   #if EV_FORK_ENABLE
747   EV_BEGIN_WATCHER (fork, fork)
748     void set () { }
749   EV_END_WATCHER (fork, fork)
750   #endif
751
752   #undef EV_PX
753   #undef EV_PX_
754   #undef EV_CONSTRUCT
755   #undef EV_BEGIN_WATCHER
756   #undef EV_END_WATCHER
757
758 }
759
760 #endif
761