summaryrefslogtreecommitdiff
path: root/libs/pbd
diff options
context:
space:
mode:
Diffstat (limited to 'libs/pbd')
-rw-r--r--libs/pbd/controllable.cc2
-rw-r--r--libs/pbd/pbd/command.h5
-rw-r--r--libs/pbd/pbd/controllable.h11
-rw-r--r--libs/pbd/pbd/destructible.h16
-rw-r--r--libs/pbd/pbd/memento_command.h16
-rw-r--r--libs/pbd/pbd/shiva.h78
-rw-r--r--libs/pbd/pbd/statefuldestructible.h12
-rw-r--r--libs/pbd/pbd/undo.h2
-rw-r--r--libs/pbd/undo.cc37
9 files changed, 128 insertions, 51 deletions
diff --git a/libs/pbd/controllable.cc b/libs/pbd/controllable.cc
index 80c6811e6a..2264a955ae 100644
--- a/libs/pbd/controllable.cc
+++ b/libs/pbd/controllable.cc
@@ -6,7 +6,7 @@
using namespace PBD;
-sigc::signal<void,Controllable*> Controllable::GoingAway;
+sigc::signal<void,Controllable*> Controllable::Destroyed;
sigc::signal<bool,Controllable*> Controllable::StartLearning;
sigc::signal<void,Controllable*> Controllable::StopLearning;
diff --git a/libs/pbd/pbd/command.h b/libs/pbd/pbd/command.h
index 7c367e7462..8044b51a83 100644
--- a/libs/pbd/pbd/command.h
+++ b/libs/pbd/pbd/command.h
@@ -21,10 +21,9 @@
#ifndef __lib_pbd_command_h__
#define __lib_pbd_command_h__
-#include <pbd/stateful.h>
-#include <pbd/destructible.h>
+#include <pbd/statefuldestructible.h>
-class Command : public Stateful, public PBD::Destructible
+class Command : public PBD::StatefulDestructible
{
public:
virtual ~Command() {}
diff --git a/libs/pbd/pbd/controllable.h b/libs/pbd/pbd/controllable.h
index ff8f8a9b52..c88eb298bc 100644
--- a/libs/pbd/pbd/controllable.h
+++ b/libs/pbd/pbd/controllable.h
@@ -6,17 +6,16 @@
#include <sigc++/trackable.h>
#include <sigc++/signal.h>
-#include <pbd/stateful.h>
-#include <pbd/id.h>
+#include <pbd/statefuldestructible.h>
class XMLNode;
namespace PBD {
-class Controllable : public virtual sigc::trackable, public Stateful {
+class Controllable : public PBD::StatefulDestructible {
public:
Controllable (std::string name);
- virtual ~Controllable() { GoingAway (this); }
+ virtual ~Controllable() { Destroyed (this); }
virtual void set_value (float) = 0;
virtual float get_value (void) const = 0;
@@ -25,11 +24,11 @@ class Controllable : public virtual sigc::trackable, public Stateful {
sigc::signal<void> LearningFinished;
- static sigc::signal<void,Controllable*> GoingAway;
-
static sigc::signal<bool,PBD::Controllable*> StartLearning;
static sigc::signal<void,PBD::Controllable*> StopLearning;
+ static sigc::signal<void,Controllable*> Destroyed;
+
sigc::signal<void> Changed;
int set_state (const XMLNode&);
diff --git a/libs/pbd/pbd/destructible.h b/libs/pbd/pbd/destructible.h
index 6692ff564c..7c50806334 100644
--- a/libs/pbd/pbd/destructible.h
+++ b/libs/pbd/pbd/destructible.h
@@ -5,14 +5,22 @@
namespace PBD {
-class Destructible : public virtual sigc::trackable {
- public:
- Destructible() {}
- virtual ~Destructible () {}
+/* be very very careful using this class. it does not inherit from sigc::trackable and thus
+ should only be used in multiple-inheritance situations involving another type
+ that does inherit from sigc::trackable (or sigc::trackable itself)
+*/
+class ThingWithGoingAway {
+ public:
+ virtual ~ThingWithGoingAway () {}
sigc::signal<void> GoingAway;
+};
+class Destructible : public sigc::trackable, public ThingWithGoingAway {
+ public:
+ virtual ~Destructible () {}
void drop_references () const { GoingAway(); }
+
};
}
diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h
index d42972d546..fe1aa8e7d0 100644
--- a/libs/pbd/pbd/memento_command.h
+++ b/libs/pbd/pbd/memento_command.h
@@ -28,19 +28,11 @@ using std::endl;
#include <pbd/command.h>
#include <pbd/stacktrace.h>
#include <pbd/xml++.h>
+#include <pbd/shiva.h>
+
#include <sigc++/slot.h>
#include <typeinfo>
-/* grrr, strict C++ says that static member functions are not C functions, but we also want
- to be able to pack this into a sigc::ptr_fun and not sigc::mem_fun, so we have to make
- it a genuine function rather than a member.
-*/
-
-static void object_death (Command* mc) {
- cerr << "\n\n\n---> OBJECT DEATH FIRED FOR " << mc << endl;
- delete mc;
-}
-
/** This command class is initialized with before and after mementos
* (from Stateful::get_state()), so undo becomes restoring the before
* memento, and redo is restoring the after memento.
@@ -55,8 +47,8 @@ class MementoCommand : public Command
XMLNode *after
)
: obj(object), before(before), after(after) {
- cerr << "MC @ " << this << " is a " << typeid (obj_T).name() << endl;
- obj.GoingAway.connect (sigc::bind (sigc::ptr_fun (object_death), static_cast<Command*>(this)));
+ /* catch destruction of the object */
+ new PBD::Shiva<obj_T,MementoCommand<obj_T> > (object, *this);
}
~MementoCommand () {
diff --git a/libs/pbd/pbd/shiva.h b/libs/pbd/pbd/shiva.h
index 5110f48332..53b613ea2b 100644
--- a/libs/pbd/pbd/shiva.h
+++ b/libs/pbd/pbd/shiva.h
@@ -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 ();
}
diff --git a/libs/pbd/pbd/statefuldestructible.h b/libs/pbd/pbd/statefuldestructible.h
index e78cc4bdaa..708c10fc8e 100644
--- a/libs/pbd/pbd/statefuldestructible.h
+++ b/libs/pbd/pbd/statefuldestructible.h
@@ -5,9 +5,21 @@
#include <pbd/destructible.h>
namespace PBD {
+
class StatefulDestructible : public Stateful, public Destructible
{
};
+
+/* be very very careful using this class. it does not inherit from sigc::trackable and thus
+ should only be used in multiple-inheritance situations involving another type
+ that does inherit from sigc::trackable (or sigc::trackable itself)
+*/
+
+class StatefulThingWithGoingAway : public Stateful, public ThingWithGoingAway
+{
+};
+
}
+
#endif /* __pbd_stateful_destructible_h__ */
diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h
index 943c115af2..277c41c2af 100644
--- a/libs/pbd/pbd/undo.h
+++ b/libs/pbd/pbd/undo.h
@@ -70,6 +70,8 @@ class UndoTransaction : public Command
struct timeval _timestamp;
std::string _name;
bool _clearing;
+
+ friend void command_death (UndoTransaction*, Command *);
};
class UndoHistory
diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc
index af408a24a4..442a5439f2 100644
--- a/libs/pbd/undo.cc
+++ b/libs/pbd/undo.cc
@@ -24,31 +24,13 @@
#include <pbd/undo.h>
#include <pbd/xml++.h>
+#include <pbd/shiva.h>
#include <sigc++/bind.h>
using namespace std;
using namespace sigc;
-/* grrr, strict C++ says that static member functions are not C functions, but we also want
- to be able to pack this into a sigc::ptr_fun and not sigc::mem_fun, so we have to make
- it a genuine function rather than a member.
-*/
-
-static void command_death (UndoTransaction* ut, Command* c)
-{
- if (ut->clearing()) {
- return;
- }
-
- ut->remove_command (c);
-
- if (ut->empty()) {
- delete ut;
- }
-}
-
-
UndoTransaction::UndoTransaction ()
{
_clearing = false;
@@ -68,6 +50,20 @@ UndoTransaction::~UndoTransaction ()
clear ();
}
+void
+command_death (UndoTransaction* ut, Command* c)
+{
+ if (ut->clearing()) {
+ return;
+ }
+
+ ut->remove_command (c);
+
+ if (ut->empty()) {
+ delete ut;
+ }
+}
+
UndoTransaction&
UndoTransaction::operator= (const UndoTransaction& rhs)
{
@@ -81,7 +77,8 @@ UndoTransaction::operator= (const UndoTransaction& rhs)
void
UndoTransaction::add_command (Command *const action)
{
- action->GoingAway.connect (bind (sigc::ptr_fun (command_death), this, const_cast<Command*>(action)));
+ /* catch death */
+ new PBD::ProxyShiva<Command,UndoTransaction> (*action, *this, &command_death);
actions.push_back (action);
}