The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / libev / ev++.h @ 90fc8d36

History | View | Annotate | Download (19.4 KB)

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