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