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, 9 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

# User Rev Content
1 pippijn 1.1 /*
2 pippijn 1.2 * $Id: callback.h.in,v 1.1 2007-07-19 08:24:50 pippijn Exp $
3 pippijn 1.1 */
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