From 71ac083429575ea21ffff97c07a2ec18c4852cc7 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sun, 30 Nov 2008 23:16:57 +0000 Subject: [PATCH] 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 --- libs/pbd/pbd/memento_command.h | 2 +- libs/pbd/pbd/shiva.h | 21 +++++++++++---------- libs/pbd/pbd/undo.h | 9 ++++++++- 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 > (object, *this); + new PBD::PairedShiva > (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 -class Shiva { +class Shiva : public sigc::trackable +{ public: Shiva (ObjectWithGoingAway& emitter, ObjectToBeDestroyed& receiver) { @@ -58,15 +59,15 @@ class Shiva { }; template -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 -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 #include #include +#include typedef sigc::slot 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 actions; + std::list*> 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 #include -#include #include @@ -78,8 +77,10 @@ UndoTransaction::operator= (const UndoTransaction& rhs) void UndoTransaction::add_command (Command *const action) { - /* catch death */ - new PBD::ProxyShiva (*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 (*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*>::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; } }