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
This commit is contained in:
Paul Davis 2008-11-30 23:16:57 +00:00
parent 2542b776c5
commit 71ac083429
4 changed files with 41 additions and 15 deletions

View file

@ -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 () {

View file

@ -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) {

View file

@ -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

View file

@ -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;
}
}