diff options
Diffstat (limited to 'libs/pbd')
-rw-r--r-- | libs/pbd/controllable.cc | 2 | ||||
-rw-r--r-- | libs/pbd/pbd/command.h | 5 | ||||
-rw-r--r-- | libs/pbd/pbd/controllable.h | 11 | ||||
-rw-r--r-- | libs/pbd/pbd/destructible.h | 16 | ||||
-rw-r--r-- | libs/pbd/pbd/memento_command.h | 16 | ||||
-rw-r--r-- | libs/pbd/pbd/shiva.h | 78 | ||||
-rw-r--r-- | libs/pbd/pbd/statefuldestructible.h | 12 | ||||
-rw-r--r-- | libs/pbd/pbd/undo.h | 2 | ||||
-rw-r--r-- | libs/pbd/undo.cc | 37 |
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); } |