PageRenderTime 119ms CodeModel.GetById 67ms app.highlight 45ms RepoModel.GetById 0ms app.codeStats 1ms

/src/libev/ev++.h

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