ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libev/ev++.h
Revision: 1.6
Committed: Wed Nov 14 06:08:13 2007 UTC (16 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-0_9, rel-1_1, rel-1_2
Changes since 1.5: +8 -9 lines
Log Message:
use a static method as thunk, saving codesize and better hiding. didn't know this was possible

File Contents

# User Rev Content
1 root 1.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 root 1.2 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 root 1.1 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 root 1.4 #define EV_BEGIN_WATCHER(cppstem,cstem) \
97 root 1.1 \
98     struct cppstem : ev_ ## cstem, callback<cppstem> \
99     { \
100     EV_CONSTRUCT (cppstem) \
101     { \
102 root 1.6 ev_init (static_cast<ev_ ## cstem *>(this), thunk); \
103 root 1.1 } \
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 root 1.3 ~cppstem () \
131     { \
132     stop (); \
133     } \
134     \
135 root 1.1 private: \
136     \
137     cppstem (const cppstem &o) \
138     : callback<cppstem> (this, (void (cppstem::*)(cppstem &, int))0) \
139     { /* disabled */ } \
140 root 1.6 \
141 root 1.1 void operator =(const cppstem &o) { /* disabled */ } \
142     \
143 root 1.6 static void thunk (EV_P_ struct ev_ ## cstem *w, int revents) \
144     { \
145     (*static_cast<cppstem *>(w))(revents); \
146     } \
147     \
148 root 1.1 public:
149    
150 root 1.4 #define EV_END_WATCHER(cppstem,cstem) \
151 root 1.6 };
152 root 1.4
153     EV_BEGIN_WATCHER (io, io)
154 root 1.1 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 root 1.4 EV_END_WATCHER (io, io)
176 root 1.1
177 root 1.4 EV_BEGIN_WATCHER (timer, timer)
178 root 1.1 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 root 1.4 EV_END_WATCHER (timer, timer)
197 root 1.1
198 root 1.3 #if EV_PERIODICS
199 root 1.4 EV_BEGIN_WATCHER (periodic, periodic)
200 root 1.1 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 root 1.4 EV_END_WATCHER (periodic, periodic)
219 root 1.3 #endif
220 root 1.1
221 root 1.4 EV_BEGIN_WATCHER (idle, idle)
222     EV_END_WATCHER (idle, idle)
223 root 1.1
224 root 1.4 EV_BEGIN_WATCHER (prepare, prepare)
225     EV_END_WATCHER (prepare, prepare)
226 root 1.1
227 root 1.4 EV_BEGIN_WATCHER (check, check)
228     EV_END_WATCHER (check, check)
229 root 1.1
230 root 1.4 EV_BEGIN_WATCHER (sig, signal)
231 root 1.1 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 root 1.4 EV_END_WATCHER (sig, signal)
245 root 1.1
246 root 1.4 EV_BEGIN_WATCHER (child, child)
247 root 1.1 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 root 1.4 EV_END_WATCHER (child, child)
261 root 1.1
262     #undef EV_CONSTRUCT
263 root 1.4 #undef EV_BEGIN_WATCHER
264 root 1.1 }
265    
266     #endif
267