]> git.llucax.com Git - software/libev.git/blob - ev++.h
minor kqueue optimisation
[software/libev.git] / ev++.h
1 #ifndef EVPP_H__
2 #define EVPP_H__
3
4 /* work in progress, don't use unless you know what you are doing */
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   #include "ev.h"
48
49   enum {
50     UNDEF    = EV_UNDEF,
51     NONE     = EV_NONE,
52     READ     = EV_READ,
53     WRITE    = EV_WRITE,
54     TIMEOUT  = EV_TIMEOUT,
55     PERIODIC = EV_PERIODIC,
56     SIGNAL   = EV_SIGNAL,
57     IDLE     = EV_IDLE,
58     CHECK    = EV_CHECK,
59     PREPARE  = EV_PREPARE,
60     CHILD    = EV_CHILD,
61     ERROR    = EV_ERROR,
62   };
63
64   typedef ev_tstamp tstamp;
65
66   inline ev_tstamp now (EV_P)
67   {
68     return ev_now (EV_A);
69   }
70
71   #if EV_MULTIPLICITY
72
73     #define EV_CONSTRUCT(cppstem)                                                       \
74       EV_P;                                                                             \
75                                                                                         \
76       void set (EV_P)                                                                   \
77       {                                                                                 \
78         this->EV_A = EV_A;                                                              \
79       }                                                                                 \
80                                                                                         \
81       template<class O1, class O2>                                                      \
82       explicit cppstem (O1 *object, void (O2::*method)(cppstem &, int), EV_P = ev_default_loop (0)) \
83       : callback<cppstem> (object, method), EV_A (EV_A)
84
85   #else
86
87     #define EV_CONSTRUCT(cppstem)                                                       \
88       template<class O1, class O2>                                                      \
89       explicit cppstem (O1 *object, void (O2::*method)(cppstem &, int))                 \
90       : callback<cppstem> (object, method)
91
92   #endif
93
94   /* using a template here would require quite a bit more lines,
95    * so a macro solution was chosen */
96   #define EV_BEGIN_WATCHER(cppstem,cstem)                                               \
97                                                                                         \
98   struct cppstem : ev_ ## cstem, callback<cppstem>                                      \
99   {                                                                                     \
100     EV_CONSTRUCT (cppstem)                                                              \
101     {                                                                                   \
102       ev_init (static_cast<ev_ ## cstem *>(this), thunk);                               \
103     }                                                                                   \
104                                                                                         \
105     bool is_active () const                                                             \
106     {                                                                                   \
107       return ev_is_active (static_cast<const ev_ ## cstem *>(this));                    \
108     }                                                                                   \
109                                                                                         \
110     bool is_pending () const                                                            \
111     {                                                                                   \
112       return ev_is_pending (static_cast<const ev_ ## cstem *>(this));                   \
113     }                                                                                   \
114                                                                                         \
115     void start ()                                                                       \
116     {                                                                                   \
117       ev_ ## cstem ## _start (EV_A_ static_cast<ev_ ## cstem *>(this));                 \
118     }                                                                                   \
119                                                                                         \
120     void stop ()                                                                        \
121     {                                                                                   \
122       ev_ ## cstem ## _stop (EV_A_ static_cast<ev_ ## cstem *>(this));                  \
123     }                                                                                   \
124                                                                                         \
125     void operator ()(int events = EV_UNDEF)                                             \
126     {                                                                                   \
127       return call (this, events);                                                       \
128     }                                                                                   \
129                                                                                         \
130     ~cppstem ()                                                                         \
131     {                                                                                   \
132       stop ();                                                                          \
133     }                                                                                   \
134                                                                                         \
135   private:                                                                              \
136                                                                                         \
137     cppstem (const cppstem &o)                                                          \
138     : callback<cppstem> (this, (void (cppstem::*)(cppstem &, int))0)                    \
139     { /* disabled */ }                                                                  \
140                                                                                         \
141     void operator =(const cppstem &o) { /* disabled */ }                                \
142                                                                                         \
143     static void thunk (EV_P_ struct ev_ ## cstem *w, int revents)                       \
144     {                                                                                   \
145       (*static_cast<cppstem *>(w))(revents);                                            \
146     }                                                                                   \
147                                                                                         \
148   public:
149
150   #define EV_END_WATCHER(cppstem,cstem)                                                 \
151   };
152
153   EV_BEGIN_WATCHER (io, io)
154     void set (int fd, int events)
155     {
156       int active = is_active ();
157       if (active) stop ();
158       ev_io_set (static_cast<ev_io *>(this), fd, events);
159       if (active) start ();
160     }
161
162     void set (int events)
163     {
164       int active = is_active ();
165       if (active) stop ();
166       ev_io_set (static_cast<ev_io *>(this), fd, events);
167       if (active) start ();
168     }
169
170     void start (int fd, int events)
171     {
172       set (fd, events);
173       start ();
174     }
175   EV_END_WATCHER (io, io)
176
177   EV_BEGIN_WATCHER (timer, timer)
178     void set (ev_tstamp after, ev_tstamp repeat = 0.)
179     {
180       int active = is_active ();
181       if (active) stop ();
182       ev_timer_set (static_cast<ev_timer *>(this), after, repeat);
183       if (active) start ();
184     }
185
186     void start (ev_tstamp after, ev_tstamp repeat = 0.)
187     {
188       set (after, repeat);
189       start ();
190     }
191
192     void again ()
193     {
194       ev_timer_again (EV_A_ static_cast<ev_timer *>(this));
195     }
196   EV_END_WATCHER (timer, timer)
197
198   #if EV_PERIODICS
199   EV_BEGIN_WATCHER (periodic, periodic)
200     void set (ev_tstamp at, ev_tstamp interval = 0.)
201     {
202       int active = is_active ();
203       if (active) stop ();
204       ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0);
205       if (active) start ();
206     }
207
208     void start (ev_tstamp at, ev_tstamp interval = 0.)
209     {
210       set (at, interval);
211       start ();
212     }
213
214     void again ()
215     {
216       ev_periodic_again (EV_A_ static_cast<ev_periodic *>(this));
217     }
218   EV_END_WATCHER (periodic, periodic)
219   #endif
220
221   EV_BEGIN_WATCHER (idle, idle)
222   EV_END_WATCHER (idle, idle)
223
224   EV_BEGIN_WATCHER (prepare, prepare)
225   EV_END_WATCHER (prepare, prepare)
226
227   EV_BEGIN_WATCHER (check, check)
228   EV_END_WATCHER (check, check)
229
230   EV_BEGIN_WATCHER (sig, signal)
231     void set (int signum)
232     {
233       int active = is_active ();
234       if (active) stop ();
235       ev_signal_set (static_cast<ev_signal *>(this), signum);
236       if (active) start ();
237     }
238
239     void start (int signum)
240     {
241       set (signum);
242       start ();
243     }
244   EV_END_WATCHER (sig, signal)
245
246   EV_BEGIN_WATCHER (child, child)
247     void set (int pid)
248     {
249       int active = is_active ();
250       if (active) stop ();
251       ev_child_set (static_cast<ev_child *>(this), pid);
252       if (active) start ();
253     }
254
255     void start (int pid)
256     {
257       set (pid);
258       start ();
259     }
260   EV_END_WATCHER (child, child)
261
262   #undef EV_CONSTRUCT
263   #undef EV_BEGIN_WATCHER
264 }
265
266 #endif
267