ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/include/callback.h.in
Revision: 1.2
Committed: Tue Aug 28 17:12:24 2007 UTC (16 years, 8 months ago) by pippijn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -1 lines
State: FILE REMOVED
Log Message:
removed old files

File Contents

# Content
1 /*
2 * $Id: callback.h.in,v 1.1 2007-07-19 08:24:50 pippijn Exp $
3 */
4
5 #ifndef CALLBACK_H
6 #define CALLBACK_H
7
8 #include <set>
9 #include <list>
10
11 namespace callback
12 {
13 class event_base;
14
15 class has_listeners
16 {
17 private:
18 typedef std::set <event_base *> sender_set;
19 typedef sender_set::const_iterator const_iterator;
20 typedef sender_set::iterator iterator;
21
22 sender_set m_senders;
23 sender_set &invokers ();
24
25 const sender_set &invokers () const;
26
27 public:
28 has_listeners ();
29 has_listeners (const has_listeners &rhs);
30
31 virtual ~has_listeners ();
32
33 has_listeners &operator = (const has_listeners &rhs);
34
35 void add_invoker (event_base *sender);
36 void remove_invoker (event_base *sender);
37
38 protected:
39 void copy_invokers (const has_listeners &rhs);
40 void disconnect_all ();
41 };
42
43 typedef has_listeners listening_base;
44
45
46 class event_base
47 {
48 public:
49 virtual ~event_base () { }
50 event_base () { }
51
52 inline bool detach (listening_base *plistener)
53 {
54 return this->listener_detach (plistener);
55 }
56
57 virtual bool listener_duplicate (const listening_base *poldlistener, listening_base *pnewlistener) = 0;
58
59 protected:
60 virtual bool listener_detach (listening_base *plistener) = 0;
61
62 template <typename list_T>
63 void free_connections (list_T &list)
64 {
65 typename list_T::const_iterator it;
66 typename list_T::const_iterator it_end = list.end ();
67
68 for (it = list.begin (); it != it_end; ++it)
69 {
70 (*it)->getdest ()->remove_invoker (this);
71 delete *it;
72 }
73
74 list.clear ();
75 }
76
77 template <typename list_T>
78 bool detach (listening_base *plistener, list_T &list)
79 {
80 typename list_T::iterator it;
81 typename list_T::iterator it_end = list.end ();
82
83 for (it = list.begin (); it != it_end; ++it)
84 {
85 if ((*it)->getdest () == plistener)
86 {
87 delete *it;
88 list.erase (it);
89 plistener->remove_invoker (this);
90
91 return true;
92 }
93 }
94
95 return false;
96 }
97
98 template <typename listeningT, typename SetT>
99 bool duplicate_connection (const listeningT *oldtarget, listeningT *newtarget, SetT &list)
100 {
101 typename SetT::iterator it = list.begin ();
102 typename SetT::iterator it_end = list.end ();
103
104 bool ret = false;
105 for (; it != it_end; ++it)
106 {
107 if ((*it)->getdest () == oldtarget)
108 {
109 list.push_back ((*it)->duplicate (newtarget));
110 ret = true;
111 }
112 }
113 return ret;
114 }
115
116 template <typename SetT>
117 void copy_connections (const SetT &src, SetT &tgt)
118 {
119 if (&src == &tgt)
120 return ;
121 typename SetT::const_iterator it = src.begin ();
122 typename SetT::const_iterator it_end = src.end ();
123 typedef typename SetT::value_type ConT;
124 ConT clone = 0;
125 for (; it != it_end; ++it)
126 {
127 clone = (*it)->clone ();
128 if (!clone)
129 continue;
130 clone->getdest ()->add_invoker (this);
131 tgt.push_back (clone);
132 }
133 }
134 };
135
136 class connection_base0
137 {
138 public:
139 virtual ~connection_base0 () { }
140 typedef connection_base0 this_type;
141 virtual listening_base *getdest () const = 0;
142 virtual void invoke () const = 0;
143
144 virtual this_type *clone () const = 0;
145 virtual this_type *duplicate (listening_base *pnewdest) const = 0;
146 };
147
148
149 template <class arg1_type>
150 class connection_base1
151 {
152 public:
153 virtual ~connection_base1 () { }
154 typedef connection_base1 <arg1_type> this_type;
155 virtual listening_base *getdest () const = 0;
156 virtual void invoke (arg1_type) const = 0;
157
158 virtual this_type *clone () const = 0;
159 virtual this_type *duplicate (listening_base *pnewdest) const = 0;
160 };
161
162
163 template <class dest_type>
164 class connection0 : public connection_base0
165 {
166 public:
167 typedef connection_base0 base_type;
168 typedef connection0<dest_type> this_type;
169
170 typedef void (dest_type::*listener_fun) ();
171 connection0 (): m_pobject (0), m_pmemfun (0){}
172
173 virtual ~connection0 () { }
174
175 connection0 (dest_type *pobject, listener_fun pmemfun): m_pobject (pobject), m_pmemfun (pmemfun){}
176
177 virtual base_type *clone () const
178 {
179 return new this_type (*this);
180 }
181
182 virtual base_type *duplicate (listening_base *pnewdest) const
183 {
184 return new this_type (dynamic_cast <dest_type *> (pnewdest), m_pmemfun);
185 }
186
187 virtual void invoke () const
188 {
189 (m_pobject->*m_pmemfun) ();
190 }
191
192 virtual listening_base *getdest () const
193 {
194 return m_pobject;
195 }
196
197 private:
198 dest_type *m_pobject;
199 listener_fun m_pmemfun;
200 };
201
202 template <class dest_type, class arg1_type>
203 class connection1 : public connection_base1<arg1_type>
204 {
205 public:
206 typedef connection_base1<arg1_type> base_type;
207 typedef connection1<dest_type, arg1_type> this_type;
208 typedef void (dest_type::*listener_fun) (arg1_type);
209 connection1 (): m_pobject (0), m_pmemfun (0){}
210
211 connection1 (dest_type *pobject, listener_fun pmemfun): m_pobject (pobject), m_pmemfun (pmemfun){}
212
213 virtual ~connection1 () { }
214
215 virtual base_type *clone () const
216 {
217 return new this_type (*this);
218 }
219
220 virtual base_type *duplicate (listening_base *pnewdest) const
221 {
222 return new this_type (dynamic_cast <dest_type *> (pnewdest), m_pmemfun);
223 }
224
225 virtual void invoke (arg1_type a1) const
226 {
227 (m_pobject->*m_pmemfun) (a1);
228 }
229
230 virtual listening_base *getdest () const
231 {
232 return m_pobject;
233 }
234
235 private:
236 dest_type *m_pobject;
237 listener_fun m_pmemfun;
238 };
239
240
241 class event0 : public event_base
242 {
243 public:
244 typedef std::list <connection_base0 *> connection_list;
245
246 event0 () { }
247
248 event0 (const event0 &s): event_base (s)
249 {
250 this->copy_connections (s.connections (), this->connections ());
251 }
252
253 event0 &operator = (const event0 &s)
254 {
255 this->copy_connections (s.connections (), this->connections ());
256 return *this;
257 }
258
259 virtual ~event0 ()
260 {
261 this->disconnect_all ();
262 }
263
264 void disconnect_all ()
265 {
266 this->free_connections (this->connections ());
267 }
268
269
270 template <class desttype>
271 void attach (desttype *pclass, void (desttype::*pmemfun) ())
272 {
273 connection_base0 *conn = new connection0<desttype> (pclass, pmemfun);
274 this->connections ().push_back (conn);
275 pclass->add_invoker (this);
276 }
277
278
279 bool listener_duplicate (const listening_base *oldtarget, listening_base *newtarget)
280 {
281 return this->duplicate_connection (oldtarget, newtarget, this->connections ());
282 }
283
284
285 void invoke () const
286 {
287 connection_list::const_iterator it;
288 connection_list::const_iterator end = this->connections ().end ();
289
290 for (it = this->connections ().begin (); it != end; ++it)
291 (*it)->invoke ();
292 }
293
294 void operator () () const
295 {
296 this->invoke ();
297 }
298
299 protected:
300 connection_list &connections ()
301 {
302 return this->m_connected_listeners;
303 }
304
305 const connection_list &connections () const
306 {
307 return this->m_connected_listeners;
308 }
309
310 bool listener_detach (listening_base *plistener)
311 {
312 return this->detach (plistener, this->connections ());
313 }
314
315 private:
316 connection_list m_connected_listeners;
317 };
318
319 template <class arg1_type>
320 class event1 : public event_base
321 {
322 public:
323 typedef std::list<connection_base1<arg1_type> *> connection_list;
324
325 event1 () { }
326
327 event1 (const event1 <arg1_type> &s): event_base (s) { }
328
329 template <class dest_type>
330 void attach (dest_type *pclass, void (dest_type::*pmemfun) (arg1_type))
331 {
332 connection_base1<arg1_type> *conn = new connection1<dest_type, arg1_type> (pclass, pmemfun);
333 this->connections ().push_back (conn);
334 pclass->add_invoker (this);
335 }
336
337 void invoke (arg1_type a1) const
338 {
339 typename connection_list::const_iterator it;
340 typename connection_list::const_iterator it_end = this->connections ().end ();
341
342 for (it = this->connections ().begin (); it != it_end; ++it)
343 {
344 (*it)->invoke (a1);
345 }
346 }
347
348 void operator () (arg1_type a1) const
349 {
350 this->invoke (a1);
351 }
352
353 event1 &operator = (const event1 &s)
354 {
355 this->copy_connections (s.connections (), this->connections ());
356 return *this;
357 }
358
359 bool listener_duplicate (const listening_base *oldtarget, listening_base *newtarget)
360 {
361 return this->duplicate_connection (oldtarget, newtarget, this->connections ());
362 }
363
364 ~event1 ()
365 {
366 this->disconnect_all ();
367 }
368
369 void disconnect_all ()
370 {
371 this->free_connections (connections ());
372 }
373
374 protected:
375 connection_list &connections ()
376 {
377 return this->m_connected_listeners;
378 }
379
380 const connection_list &connections () const
381 {
382 return this->m_connected_listeners;
383 }
384
385 bool listener_detach (listening_base *plistener)
386 {
387 return this->detach (plistener, this->connections ());
388 }
389
390 private:
391 connection_list m_connected_listeners;
392 };
393
394 @CALLBACKS@
395
396 } // namespace callback
397
398 class has_callbacks
399 {
400 protected:
401 struct callbacks
402 {
403 callback::event1 <has_callbacks *> created;
404 callback::event1 <has_callbacks *> destroyed;
405 };
406
407 static callbacks callback;
408
409 has_callbacks ();
410 ~has_callbacks ();
411 };
412
413 #endif // CALLBACK_H