the useless commit: add copyright messages to all(?) files that need it
[ardour.git] / libs / pbd / pbd / shiva.h
1 /*
2     Copyright (C) 2000-2007 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __pbd_shiva_h__
21 #define __pbd_shiva_h__
22
23 #include <sigc++/sigc++.h>
24
25 namespace PBD {
26
27 /* named after the Hindu god Shiva, The Destroyer */
28
29 template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
30 class Shiva {
31   public:
32         Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
33
34                 /* if the emitter goes away, destroy the receiver */
35
36                 _connection = emitter.GoingAway.connect 
37                         (sigc::bind (sigc::mem_fun 
38                                      (*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
39                                      &receiver));
40         }
41
42         ~Shiva() { 
43                 forget ();
44         }
45
46   private:
47         sigc::connection _connection;
48
49         void destroy (ObjectToBeDestroyed* obj) {
50                 delete obj;
51                 forget ();
52         }
53
54         void forget () {
55                 _connection.disconnect ();
56         }
57                         
58 };
59
60 template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
61 class ProxyShiva {
62   public:
63         ProxyShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver, void (*callback)(ObjectToBeDestroyed*, ObjectWithGoingAway*)) {
64
65                 /* if the emitter goes away, destroy the receiver */
66
67                 _callback = callback;
68                 _callback_argument1 = &receiver;
69                 _callback_argument2 = &emitter;
70
71                 _connection = emitter.GoingAway.connect 
72                         (sigc::bind (sigc::mem_fun 
73                                      (*this, &ProxyShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
74                                      &receiver));
75         }
76
77         ~ProxyShiva() { 
78                 forget ();
79         }
80
81   private:
82         sigc::connection _connection;
83         void (*_callback) (ObjectToBeDestroyed*, ObjectWithGoingAway*);
84         ObjectToBeDestroyed* _callback_argument1;
85         ObjectWithGoingAway* _callback_argument2;
86
87         void destroy (ObjectToBeDestroyed* obj) {
88                 /* callback must destroy obj if appropriate, not done here */
89                 _callback (obj, _callback_argument2);
90                 forget ();
91         }
92
93         void forget () {
94                 _connection.disconnect ();
95         }
96 };
97
98 template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
99 class PairedShiva {
100   public:
101         PairedShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
102
103                 /* if the emitter goes away, destroy the receiver */
104
105                 _connection1 = emitter.GoingAway.connect 
106                         (sigc::bind (sigc::mem_fun 
107                                      (*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
108                                      &receiver));
109
110                 /* if the receiver goes away, forget all this nonsense */
111
112                 _connection2 = receiver.GoingAway.connect 
113                         (sigc::mem_fun (*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget));
114         }
115
116         ~PairedShiva() { 
117                 forget ();
118         }
119
120   private:
121         sigc::connection _connection1;
122         sigc::connection _connection2;
123
124         void destroy (ObjectToBeDestroyed* obj) {
125                 delete obj;
126                 forget ();
127         }
128
129         void forget () {
130                 _connection1.disconnect ();
131                 _connection2.disconnect ();
132         }
133                         
134 };
135
136 }
137
138 #endif /* __pbd_shiva_h__ */