]> git.llucax.com Git - software/libev.git/blob - ev++.h
implement EVFLAG_FORKCHECK
[software/libev.git] / ev++.h
1 #ifndef EVPP_H__
2 #define EVPP_H__
3
4 #include "ev.h"
5
6 namespace ev {
7
8   template<class watcher>
9   class callback
10   {
11     struct klass; // it is vital that this is never defined
12
13     klass *o;
14     void (klass::*m)(watcher &, int);
15
16   public:
17     template<class O1, class O2>
18     explicit callback (O1 *object, void (O2::*method)(watcher &, int))
19     {
20       o = reinterpret_cast<klass *>(object);
21       m = reinterpret_cast<void (klass::*)(watcher &, int)>(method);
22     }
23
24     // this works because a standards-compliant C++ compiler
25     // basically can't help it: it doesn't have the knowledge
26     // required to miscompile (klass is not defined anywhere
27     // and nothing is known about the constructor arguments) :)
28     void call (watcher *w, int revents)
29     {
30       (o->*m) (*w, revents);
31     }
32   };
33
34   enum {
35     UNDEF    = EV_UNDEF,
36     NONE     = EV_NONE,
37     READ     = EV_READ,
38     WRITE    = EV_WRITE,
39     TIMEOUT  = EV_TIMEOUT,
40     PERIODIC = EV_PERIODIC,
41     SIGNAL   = EV_SIGNAL,
42     CHILD    = EV_CHILD,
43     STAT     = EV_STAT,
44     IDLE     = EV_IDLE,
45     CHECK    = EV_CHECK,
46     PREPARE  = EV_PREPARE,
47     FORK     = EV_FORK,
48     EMBED    = EV_EMBED,
49     ERROR    = EV_ERROR,
50   };
51
52   typedef ev_tstamp tstamp;
53
54   inline ev_tstamp now (EV_P)
55   {
56     return ev_now (EV_A);
57   }
58
59   #if EV_MULTIPLICITY
60
61     #define EV_CONSTRUCT(cppstem)                                                       \
62       EV_P;                                                                             \
63                                                                                         \
64       void set (EV_P)                                                                   \
65       {                                                                                 \
66         this->EV_A = EV_A;                                                              \
67       }                                                                                 \
68                                                                                         \
69       template<class O1, class O2>                                                      \
70       explicit cppstem (O1 *object, void (O2::*method)(cppstem &, int), EV_P = ev_default_loop (0)) \
71       : callback<cppstem> (object, method), EV_A (EV_A)
72
73   #else
74
75     #define EV_CONSTRUCT(cppstem)                                                       \
76       template<class O1, class O2>                                                      \
77       explicit cppstem (O1 *object, void (O2::*method)(cppstem &, int))                 \
78       : callback<cppstem> (object, method)
79
80   #endif
81
82   /* using a template here would require quite a bit more lines,
83    * so a macro solution was chosen */
84   #define EV_BEGIN_WATCHER(cppstem,cstem)                                               \
85                                                                                         \
86   struct cppstem : ev_ ## cstem, callback<cppstem>                                      \
87   {                                                                                     \
88     EV_CONSTRUCT (cppstem)                                                              \
89     {                                                                                   \
90       ev_init (static_cast<ev_ ## cstem *>(this), thunk);                               \
91     }                                                                                   \
92                                                                                         \
93     bool is_active () const                                                             \
94     {                                                                                   \
95       return ev_is_active (static_cast<const ev_ ## cstem *>(this));                    \
96     }                                                                                   \
97                                                                                         \
98     bool is_pending () const                                                            \
99     {                                                                                   \
100       return ev_is_pending (static_cast<const ev_ ## cstem *>(this));                   \
101     }                                                                                   \
102                                                                                         \
103     void start ()                                                                       \
104     {                                                                                   \
105       ev_ ## cstem ## _start (EV_A_ static_cast<ev_ ## cstem *>(this));                 \
106     }                                                                                   \
107                                                                                         \
108     void stop ()                                                                        \
109     {                                                                                   \
110       ev_ ## cstem ## _stop (EV_A_ static_cast<ev_ ## cstem *>(this));                  \
111     }                                                                                   \
112                                                                                         \
113     void operator ()(int events = EV_UNDEF)                                             \
114     {                                                                                   \
115       return call (this, events);                                                       \
116     }                                                                                   \
117                                                                                         \
118     ~cppstem ()                                                                         \
119     {                                                                                   \
120       stop ();                                                                          \
121     }                                                                                   \
122                                                                                         \
123   private:                                                                              \
124                                                                                         \
125     cppstem (const cppstem &o)                                                          \
126     : callback<cppstem> (this, (void (cppstem::*)(cppstem &, int))0)                    \
127     { /* disabled */ }                                                                  \
128                                                                                         \
129     void operator =(const cppstem &o) { /* disabled */ }                                \
130                                                                                         \
131     static void thunk (EV_P_ struct ev_ ## cstem *w, int revents)                       \
132     {                                                                                   \
133       (*static_cast<cppstem *>(w))(revents);                                            \
134     }                                                                                   \
135                                                                                         \
136   public:
137
138   #define EV_END_WATCHER(cppstem,cstem)                                                 \
139   };
140
141   EV_BEGIN_WATCHER (io, io)
142     void set (int fd, int events)
143     {
144       int active = is_active ();
145       if (active) stop ();
146       ev_io_set (static_cast<ev_io *>(this), fd, events);
147       if (active) start ();
148     }
149
150     void set (int events)
151     {
152       int active = is_active ();
153       if (active) stop ();
154       ev_io_set (static_cast<ev_io *>(this), fd, events);
155       if (active) start ();
156     }
157
158     void start (int fd, int events)
159     {
160       set (fd, events);
161       start ();
162     }
163   EV_END_WATCHER (io, io)
164
165   EV_BEGIN_WATCHER (timer, timer)
166     void set (ev_tstamp after, ev_tstamp repeat = 0.)
167     {
168       int active = is_active ();
169       if (active) stop ();
170       ev_timer_set (static_cast<ev_timer *>(this), after, repeat);
171       if (active) start ();
172     }
173
174     void start (ev_tstamp after, ev_tstamp repeat = 0.)
175     {
176       set (after, repeat);
177       start ();
178     }
179
180     void again ()
181     {
182       ev_timer_again (EV_A_ static_cast<ev_timer *>(this));
183     }
184   EV_END_WATCHER (timer, timer)
185
186   #if EV_PERIODIC_ENABLE
187   EV_BEGIN_WATCHER (periodic, periodic)
188     void set (ev_tstamp at, ev_tstamp interval = 0.)
189     {
190       int active = is_active ();
191       if (active) stop ();
192       ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0);
193       if (active) start ();
194     }
195
196     void start (ev_tstamp at, ev_tstamp interval = 0.)
197     {
198       set (at, interval);
199       start ();
200     }
201
202     void again ()
203     {
204       ev_periodic_again (EV_A_ static_cast<ev_periodic *>(this));
205     }
206   EV_END_WATCHER (periodic, periodic)
207   #endif
208
209   EV_BEGIN_WATCHER (sig, signal)
210     void set (int signum)
211     {
212       int active = is_active ();
213       if (active) stop ();
214       ev_signal_set (static_cast<ev_signal *>(this), signum);
215       if (active) start ();
216     }
217
218     void start (int signum)
219     {
220       set (signum);
221       start ();
222     }
223   EV_END_WATCHER (sig, signal)
224
225   EV_BEGIN_WATCHER (child, child)
226     void set (int pid)
227     {
228       int active = is_active ();
229       if (active) stop ();
230       ev_child_set (static_cast<ev_child *>(this), pid);
231       if (active) start ();
232     }
233
234     void start (int pid)
235     {
236       set (pid);
237       start ();
238     }
239   EV_END_WATCHER (child, child)
240
241   #if EV_STAT_ENABLE
242   EV_BEGIN_WATCHER (stat, stat)
243     void set (const char *path, ev_tstamp interval = 0.)
244     {
245       int active = is_active ();
246       if (active) stop ();
247       ev_stat_set (static_cast<ev_stat *>(this), path, interval);
248       if (active) start ();
249     }
250
251     void start (const char *path, ev_tstamp interval = 0.)
252     {
253       set (path, interval);
254       start ();
255     }
256
257     void update ()
258     {
259       ev_stat_stat (EV_A_ static_cast<ev_stat *>(this));
260     }
261   EV_END_WATCHER (stat, stat)
262   #endif
263
264   EV_BEGIN_WATCHER (idle, idle)
265     void set () { }
266   EV_END_WATCHER (idle, idle)
267
268   EV_BEGIN_WATCHER (prepare, prepare)
269     void set () { }
270   EV_END_WATCHER (prepare, prepare)
271
272   EV_BEGIN_WATCHER (check, check)
273     void set () { }
274   EV_END_WATCHER (check, check)
275
276   #if EV_EMBED_ENABLE
277   EV_BEGIN_WATCHER (embed, embed)
278     void set (struct ev_loop *loop)
279     {
280       int active = is_active ();
281       if (active) stop ();
282       ev_embed_set (static_cast<ev_embed *>(this), loop);
283       if (active) start ();
284     }
285
286     void start (struct ev_loop *embedded_loop)
287     {
288       set (embedded_loop);
289       start ();
290     }
291
292     void sweep ()
293     {
294       ev_embed_sweep (EV_A_ static_cast<ev_embed *>(this));
295     }
296   EV_END_WATCHER (embed, embed)
297   #endif
298
299   #if EV_FORK_ENABLE
300   EV_BEGIN_WATCHER (fork, fork)
301     void set () { }
302   EV_END_WATCHER (fork, fork)
303   #endif
304
305   #undef EV_CONSTRUCT
306   #undef EV_BEGIN_WATCHER
307   #undef EV_END_WATCHER
308 }
309
310 #endif
311