Merged with trunk R1141
[ardour.git] / libs / pbd / pbd / shiva.h
index 5110f483324b950485c4e8517edaa817fc8ba504..53b613ea2b0cc14e1f66e1a096a477d31145b5f6 100644 (file)
@@ -5,28 +5,96 @@
 
 namespace PBD {
 
-template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
-
 /* named after the Hindu god Shiva, The Destroyer */
 
+template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
 class Shiva {
   public:
        Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
 
                /* if the emitter goes away, destroy the receiver */
 
-               _connection1 = emitter.GoingAway.connect 
+               _connection = emitter.GoingAway.connect 
                        (sigc::bind (sigc::mem_fun 
                                     (*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
                                     &receiver));
+       }
+
+       ~Shiva() { 
+               forget ();
+       }
+
+  private:
+       sigc::connection _connection;
+
+       void destroy (ObjectToBeDestroyed* obj) {
+               delete obj;
+               forget ();
+       }
+
+       void forget () {
+               _connection.disconnect ();
+       }
+                       
+};
+
+template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
+class ProxyShiva {
+  public:
+       ProxyShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver, void (*callback)(ObjectToBeDestroyed*, ObjectWithGoingAway*)) {
+
+               /* if the emitter goes away, destroy the receiver */
+
+               _callback = callback;
+               _callback_argument1 = &receiver;
+               _callback_argument2 = &emitter;
+
+               _connection = emitter.GoingAway.connect 
+                       (sigc::bind (sigc::mem_fun 
+                                    (*this, &ProxyShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
+                                    &receiver));
+       }
+
+       ~ProxyShiva() { 
+               forget ();
+       }
+
+  private:
+       sigc::connection _connection;
+       void (*_callback) (ObjectToBeDestroyed*, ObjectWithGoingAway*);
+       ObjectToBeDestroyed* _callback_argument1;
+       ObjectWithGoingAway* _callback_argument2;
+
+       void destroy (ObjectToBeDestroyed* obj) {
+               /* callback must destroy obj if appropriate, not done here */
+               _callback (obj, _callback_argument2);
+               forget ();
+       }
+
+       void forget () {
+               _connection.disconnect ();
+       }
+};
+
+template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed>
+class PairedShiva {
+  public:
+       PairedShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) {
+
+               /* if the emitter goes away, destroy the receiver */
+
+               _connection1 = emitter.GoingAway.connect 
+                       (sigc::bind (sigc::mem_fun 
+                                    (*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::destroy),
+                                    &receiver));
 
                /* if the receiver goes away, forget all this nonsense */
 
                _connection2 = receiver.GoingAway.connect 
-                       (sigc::mem_fun (*this, &Shiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget));
+                       (sigc::mem_fun (*this, &PairedShiva<ObjectWithGoingAway,ObjectToBeDestroyed>::forget));
        }
 
-       ~Shiva() { 
+       ~PairedShiva() { 
                forget ();
        }