summaryrefslogtreecommitdiff
path: root/libs/pbd
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2008-12-12 14:43:24 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2008-12-12 14:43:24 +0000
commitbc89fe0147c04b67141936d109c00dfd4d69cc4b (patch)
tree544ff450c40fe1f43853a8420228a26f27f1eafb /libs/pbd
parent30daaebaa2d90d6b0e8673143ccc3cacd7bd1753 (diff)
most of the 2.X->3.0 commit (up to rev 4299) except for gtk2_ardour/editor_canvas.cc; builds and runs and does a few specific things but expect it to be buggy for a while yet
git-svn-id: svn://localhost/ardour2/branches/3.0@4313 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd')
-rw-r--r--libs/pbd/command.cc1
-rw-r--r--libs/pbd/pbd/abstract_ui.cc1
-rw-r--r--libs/pbd/pbd/command.h2
-rw-r--r--libs/pbd/pbd/memento_command.h2
-rw-r--r--libs/pbd/pbd/pthread_utils.h7
-rw-r--r--libs/pbd/pbd/shiva.h21
-rw-r--r--libs/pbd/pbd/undo.h22
-rw-r--r--libs/pbd/pthread_utils.cc19
-rw-r--r--libs/pbd/undo.cc67
9 files changed, 111 insertions, 31 deletions
diff --git a/libs/pbd/command.cc b/libs/pbd/command.cc
index 011534a662..2b64c46030 100644
--- a/libs/pbd/command.cc
+++ b/libs/pbd/command.cc
@@ -20,7 +20,6 @@
#include <pbd/command.h>
#include <pbd/xml++.h>
-
XMLNode &Command::get_state()
{
XMLNode *node = new XMLNode ("Command");
diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc
index 97f19e1fe5..8e5b9ceb07 100644
--- a/libs/pbd/pbd/abstract_ui.cc
+++ b/libs/pbd/pbd/abstract_ui.cc
@@ -17,7 +17,6 @@ AbstractUI<RequestObject>::AbstractUI (string name, bool with_signal_pipes)
throw failed_constructor();
}
- PBD::ThreadCreated.connect (mem_fun (*this, &AbstractUI<RequestObject>::register_thread));
PBD::ThreadCreatedWithRequestSize.connect (mem_fun (*this, &AbstractUI<RequestObject>::register_thread_with_request_count));
}
diff --git a/libs/pbd/pbd/command.h b/libs/pbd/pbd/command.h
index a66485bc0d..3fac531591 100644
--- a/libs/pbd/pbd/command.h
+++ b/libs/pbd/pbd/command.h
@@ -26,7 +26,7 @@
class Command : public PBD::StatefulDestructible
{
public:
- virtual ~Command() {}
+ virtual ~Command() { /* NOTE: derived classes must call drop_references() */ }
virtual void operator() () = 0;
diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h
index fdc7527dc6..660e5875d5 100644
--- a/libs/pbd/pbd/memento_command.h
+++ b/libs/pbd/pbd/memento_command.h
@@ -43,7 +43,7 @@ public:
: 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/pthread_utils.h b/libs/pbd/pbd/pthread_utils.h
index 9fa6ba4ce4..dd91e0a2b1 100644
--- a/libs/pbd/pbd/pthread_utils.h
+++ b/libs/pbd/pbd/pthread_utils.h
@@ -35,8 +35,11 @@ void pthread_exit_pbd (void* status);
std::string pthread_name ();
namespace PBD {
- extern sigc::signal<void,pthread_t,std::string> ThreadCreated;
- extern sigc::signal<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
+ extern void notify_gui_about_thread_creation (pthread_t, std::string, int requests = 256);
+ extern void notify_gui_about_thread_exit (pthread_t);
+
+ extern sigc::signal<void,pthread_t> ThreadLeaving;
+ extern sigc::signal<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
}
#endif /* __pbd_pthread_utils__ */
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 8f1716d09f..cf1f6f3470 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;
@@ -61,10 +61,17 @@ class UndoTransaction : public Command
private:
std::list<Command*> actions;
+ std::list<PBD::ProxyShiva<Command,UndoTransaction>*> shivas;
struct timeval _timestamp;
bool _clearing;
friend void command_death (UndoTransaction*, Command *);
+
+ friend class UndoHistory;
+
+ ~UndoTransaction ();
+ void about_to_explicitly_delete ();
+
};
class UndoHistory : public sigc::trackable
@@ -87,17 +94,24 @@ class UndoHistory : public sigc::trackable
void clear_undo ();
void clear_redo ();
+ /* returns all or part of the history.
+ If depth==0 it returns just the top
+ node. If depth<0, it returns everything.
+ If depth>0, it returns state for that
+ many elements of the history, or
+ the full history, whichever is smaller.
+ */
+
XMLNode &get_state(int32_t depth = 0);
void save_state();
- void set_depth (int32_t);
- int32_t get_depth() const { return _depth; }
+ void set_depth (uint32_t);
sigc::signal<void> Changed;
private:
bool _clearing;
- int32_t _depth;
+ uint32_t _depth;
std::list<UndoTransaction*> UndoList;
std::list<UndoTransaction*> RedoList;
diff --git a/libs/pbd/pthread_utils.cc b/libs/pbd/pthread_utils.cc
index 3408f2c0b7..c63f988af3 100644
--- a/libs/pbd/pthread_utils.cc
+++ b/libs/pbd/pthread_utils.cc
@@ -30,14 +30,31 @@ using namespace std;
typedef std::map<string,pthread_t> ThreadMap;
static ThreadMap all_threads;
static pthread_mutex_t thread_map_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t gui_notify_lock = PTHREAD_MUTEX_INITIALIZER;
namespace PBD {
- sigc::signal<void,pthread_t,std::string> ThreadCreated;
+ sigc::signal<void,pthread_t> ThreadLeaving;
sigc::signal<void,pthread_t,std::string,uint32_t> ThreadCreatedWithRequestSize;
}
using namespace PBD;
+void
+PBD::notify_gui_about_thread_creation (pthread_t thread, std::string str, int request_count)
+{
+ pthread_mutex_lock (&gui_notify_lock);
+ ThreadCreatedWithRequestSize (thread, str, request_count);
+ pthread_mutex_unlock (&gui_notify_lock);
+}
+
+void
+PBD::notify_gui_about_thread_exit (pthread_t thread)
+{
+ pthread_mutex_lock (&gui_notify_lock);
+ ThreadLeaving (thread);
+ pthread_mutex_unlock (&gui_notify_lock);
+}
+
int
pthread_create_and_store (string name, pthread_t *thread, pthread_attr_t *attr, void * (*start_routine)(void *), void * arg)
{
diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc
index f04b4d9431..5365a98146 100644
--- a/libs/pbd/undo.cc
+++ b/libs/pbd/undo.cc
@@ -18,14 +18,12 @@
$Id$
*/
-#include <iostream>
#include <string>
#include <sstream>
#include <time.h>
#include <pbd/undo.h>
#include <pbd/xml++.h>
-#include <pbd/shiva.h>
#include <sigc++/bind.h>
@@ -79,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);
}
@@ -90,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
{
@@ -154,27 +169,59 @@ UndoHistory::UndoHistory ()
}
void
-UndoHistory::set_depth (int32_t d)
+UndoHistory::set_depth (uint32_t d)
{
+ UndoTransaction* ut;
+ uint32_t current_depth = UndoList.size();
+
_depth = d;
- while (_depth > 0 && UndoList.size() > (uint32_t) _depth) {
- UndoList.pop_front ();
+ if (d > current_depth) {
+ /* not even transactions to meet request */
+ return;
+ }
+
+ if (_depth > 0) {
+
+ uint32_t cnt = current_depth - d;
+
+ while (cnt--) {
+ ut = UndoList.front();
+ UndoList.pop_front ();
+ ut->about_to_explicitly_delete ();
+ delete ut;
+ }
}
}
void
UndoHistory::add (UndoTransaction* const ut)
{
+ uint32_t current_depth = UndoList.size();
+
ut->GoingAway.connect (bind (mem_fun (*this, &UndoHistory::remove), ut));
- while (_depth > 0 && UndoList.size() > (uint32_t) _depth) {
- UndoList.pop_front ();
+ /* if the current undo history is larger than or equal to the currently
+ requested depth, then pop off at least 1 element to make space
+ at the back for new one.
+ */
+
+ if ((_depth > 0) && current_depth && (current_depth >= _depth)) {
+
+ uint32_t cnt = 1 + (current_depth - _depth);
+
+ while (cnt--) {
+ UndoTransaction* ut;
+ ut = UndoList.front ();
+ UndoList.pop_front ();
+ ut->about_to_explicitly_delete ();
+ delete ut;
+ }
}
UndoList.push_back (ut);
- /* we are now owners of the transaction */
+ /* we are now owners of the transaction and must delete it when finished with it */
Changed (); /* EMIT SIGNAL */
}