fixes for endemic (compiler?) issues with virtual inheritance of sigc::trackable. NOTE: automation list undo/redo no longer operational, fix to follow

git-svn-id: svn://localhost/ardour2/trunk@1007 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis
2006-10-25 20:11:42 +00:00
parent 1b39adc4ce
commit bcd511aa3f
42 changed files with 357 additions and 122 deletions

View File

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

View File

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

View File

@@ -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&);

View File

@@ -5,14 +5,22 @@
namespace PBD {
class Destructible : public virtual sigc::trackable {
/* 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:
Destructible() {}
virtual ~Destructible () {}
virtual ~ThingWithGoingAway () {}
sigc::signal<void> GoingAway;
};
class Destructible : public sigc::trackable, public ThingWithGoingAway {
public:
virtual ~Destructible () {}
void drop_references () const { GoingAway(); }
};
}

View File

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

View File

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

View File

@@ -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__ */

View File

@@ -70,6 +70,8 @@ class UndoTransaction : public Command
struct timeval _timestamp;
std::string _name;
bool _clearing;
friend void command_death (UndoTransaction*, Command *);
};
class UndoHistory

View File

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