diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-11-30 23:16:57 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-11-30 23:16:57 +0000 |
commit | 71ac083429575ea21ffff97c07a2ec18c4852cc7 (patch) | |
tree | c4d55bd1e9835aca7715ae42d9dc6b5576b95b95 | |
parent | 2542b776c5128bee46528b4b6d6b342772594953 (diff) |
fix up monumental botch job regarding undo history/object/command management
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@4274 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | libs/pbd/pbd/memento_command.h | 2 | ||||
-rw-r--r-- | libs/pbd/pbd/shiva.h | 21 | ||||
-rw-r--r-- | libs/pbd/pbd/undo.h | 9 | ||||
-rw-r--r-- | libs/pbd/undo.cc | 24 |
4 files changed, 41 insertions, 15 deletions
diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h index d913b2c0fe..d1d1bdefaa 100644 --- a/libs/pbd/pbd/memento_command.h +++ b/libs/pbd/pbd/memento_command.h @@ -47,7 +47,7 @@ class MementoCommand : public Command ) : obj(object), before(before), after(after) { /* catch destruction of the object */ - new PBD::Shiva<obj_T,MementoCommand<obj_T> > (object, *this); + new PBD::PairedShiva<obj_T,MementoCommand<obj_T> > (object, *this); } ~MementoCommand () { diff --git a/libs/pbd/pbd/shiva.h b/libs/pbd/pbd/shiva.h index 2e53ff65f5..90adad6250 100644 --- a/libs/pbd/pbd/shiva.h +++ b/libs/pbd/pbd/shiva.h @@ -27,7 +27,8 @@ namespace PBD { /* named after the Hindu god Shiva, The Destroyer */ template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed> -class Shiva { +class Shiva : public sigc::trackable +{ public: Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) { @@ -58,15 +59,15 @@ class Shiva { }; template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed> -class ProxyShiva { +class ProxyShiva : public sigc::trackable +{ 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; + _callback_argument = &emitter; _connection = emitter.GoingAway.connect (sigc::bind (sigc::mem_fun @@ -74,19 +75,18 @@ class ProxyShiva { &receiver)); } - ~ProxyShiva() { + ~ProxyShiva () { forget (); } private: sigc::connection _connection; void (*_callback) (ObjectToBeDestroyed*, ObjectWithGoingAway*); - ObjectToBeDestroyed* _callback_argument1; - ObjectWithGoingAway* _callback_argument2; + ObjectWithGoingAway* _callback_argument; void destroy (ObjectToBeDestroyed* obj) { /* callback must destroy obj if appropriate, not done here */ - _callback (obj, _callback_argument2); + _callback (obj, _callback_argument); forget (); } @@ -96,7 +96,8 @@ class ProxyShiva { }; template<typename ObjectWithGoingAway, typename ObjectToBeDestroyed> -class PairedShiva { +class PairedShiva : public sigc::trackable +{ public: PairedShiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) { diff --git a/libs/pbd/pbd/undo.h b/libs/pbd/pbd/undo.h index c5f60c51af..6ee69e75e4 100644 --- a/libs/pbd/pbd/undo.h +++ b/libs/pbd/pbd/undo.h @@ -27,6 +27,7 @@ #include <sigc++/bind.h> #include <sys/time.h> #include <pbd/command.h> +#include <pbd/shiva.h> typedef sigc::slot<void> UndoAction; @@ -36,7 +37,6 @@ class UndoTransaction : public Command UndoTransaction (); UndoTransaction (const UndoTransaction&); UndoTransaction& operator= (const UndoTransaction&); - ~UndoTransaction (); void clear (); bool empty() const; @@ -66,11 +66,18 @@ class UndoTransaction : public Command private: std::list<Command*> actions; + std::list<PBD::ProxyShiva<Command,UndoTransaction>*> shivas; struct timeval _timestamp; std::string _name; bool _clearing; friend void command_death (UndoTransaction*, Command *); + + friend class UndoHistory; + + ~UndoTransaction (); + void about_to_explicitly_delete (); + }; class UndoHistory : public sigc::trackable diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc index 43baad35d2..2e2686d558 100644 --- a/libs/pbd/undo.cc +++ b/libs/pbd/undo.cc @@ -24,7 +24,6 @@ #include <pbd/undo.h> #include <pbd/xml++.h> -#include <pbd/shiva.h> #include <sigc++/bind.h> @@ -78,8 +77,10 @@ UndoTransaction::operator= (const UndoTransaction& rhs) void UndoTransaction::add_command (Command *const action) { - /* catch death */ - new PBD::ProxyShiva<Command,UndoTransaction> (*action, *this, &command_death); + /* catch death of command (e.g. caused by death of object to + which it refers. + */ + shivas.push_back (new PBD::ProxyShiva<Command,UndoTransaction> (*action, *this, &command_death)); actions.push_back (action); } @@ -89,6 +90,21 @@ UndoTransaction::remove_command (Command* const action) actions.remove (action); } +void +UndoTransaction::about_to_explicitly_delete () +{ + /* someone is going to call our destructor and its not Shiva, + the god of destruction and chaos. This happens when an UndoHistory + is pruning itself. we must remove Shivas to avoid the god + striking us down a second time, unnecessarily and illegally. + */ + + for (list<PBD::ProxyShiva<Command,UndoTransaction>*>::iterator i = shivas.begin(); i != shivas.end(); ++i) { + delete *i; + } + shivas.clear (); +} + bool UndoTransaction::empty () const { @@ -172,6 +188,7 @@ UndoHistory::set_depth (uint32_t d) while (cnt--) { ut = UndoList.front(); UndoList.pop_front (); + ut->about_to_explicitly_delete (); delete ut; } } @@ -197,6 +214,7 @@ UndoHistory::add (UndoTransaction* const ut) UndoTransaction* ut; ut = UndoList.front (); UndoList.pop_front (); + ut->about_to_explicitly_delete (); delete ut; } } |