Merged with trunk R1141
[ardour.git] / libs / pbd / pbd / shiva.h
1 #ifndef __pbd_shiva_h__
2 #define __pbd_shiva_h__
3
4 #include <sigc++/sigc++.h>
5
6 namespace PBD {
7
8 /* named after the Hindu god Shiva, The Destroyer */
9
10 template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
11 class Shiva {
12   public:
13         Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
14
15                 /* if the emitter goes away, destroy the receiver */
16
17                 _connection = emitter.GoingAway.connect 
18                         (sigc::bind (sigc::mem_fun 
19                                      (*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
20                                      &receiver));
21         }
22
23         ~Shiva() { 
24                 forget ();
25         }
26
27   private:
28         sigc::connection _connection;
29
30         void destroy (ObjectToBeDestroyed* obj) {
31                 delete obj;
32                 forget ();
33         }
34
35         void forget () {
36                 _connection.disconnect ();
37         }
38                         
39 };
40
41 template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
42 class ProxyShiva {
43   public:
44         ProxyShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver, void (*callback)(ObjectToBeDestroyed*, ObjectWithGoingAway*)) {
45
46                 /* if the emitter goes away, destroy the receiver */
47
48                 _callback = callback;
49                 _callback_argument1 = &receiver;
50                 _callback_argument2 = &emitter;
51
52                 _connection = emitter.GoingAway.connect 
53                         (sigc::bind (sigc::mem_fun 
54                                      (*this, &ProxyShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
55                                      &receiver));
56         }
57
58         ~ProxyShiva() { 
59                 forget ();
60         }
61
62   private:
63         sigc::connection _connection;
64         void (*_callback) (ObjectToBeDestroyed*, ObjectWithGoingAway*);
65         ObjectToBeDestroyed* _callback_argument1;
66         ObjectWithGoingAway* _callback_argument2;
67
68         void destroy (ObjectToBeDestroyed* obj) {
69                 /* callback must destroy obj if appropriate, not done here */
70                 _callback (obj, _callback_argument2);
71                 forget ();
72         }
73
74         void forget () {
75                 _connection.disconnect ();
76         }
77 };
78
79 template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
80 class PairedShiva {
81   public:
82         PairedShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
83
84                 /* if the emitter goes away, destroy the receiver */
85
86                 _connection1 = emitter.GoingAway.connect 
87                         (sigc::bind (sigc::mem_fun 
88                                      (*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
89                                      &receiver));
90
91                 /* if the receiver goes away, forget all this nonsense */
92
93                 _connection2 = receiver.GoingAway.connect 
94                         (sigc::mem_fun (*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget));
95         }
96
97         ~PairedShiva() { 
98                 forget ();
99         }
100
101   private:
102         sigc::connection _connection1;
103         sigc::connection _connection2;
104
105         void destroy (ObjectToBeDestroyed* obj) {
106                 delete obj;
107                 forget ();
108         }
109
110         void forget () {
111                 _connection1.disconnect ();
112                 _connection2.disconnect ();
113         }
114                         
115 };
116
117 }
118
119 #endif /* __pbd_shiva_h__ */