diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-12-12 14:43:24 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-12-12 14:43:24 +0000 |
commit | bc89fe0147c04b67141936d109c00dfd4d69cc4b (patch) | |
tree | 544ff450c40fe1f43853a8420228a26f27f1eafb /libs/pbd | |
parent | 30daaebaa2d90d6b0e8673143ccc3cacd7bd1753 (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.cc | 1 | ||||
-rw-r--r-- | libs/pbd/pbd/abstract_ui.cc | 1 | ||||
-rw-r--r-- | libs/pbd/pbd/command.h | 2 | ||||
-rw-r--r-- | libs/pbd/pbd/memento_command.h | 2 | ||||
-rw-r--r-- | libs/pbd/pbd/pthread_utils.h | 7 | ||||
-rw-r--r-- | libs/pbd/pbd/shiva.h | 21 | ||||
-rw-r--r-- | libs/pbd/pbd/undo.h | 22 | ||||
-rw-r--r-- | libs/pbd/pthread_utils.cc | 19 | ||||
-rw-r--r-- | libs/pbd/undo.cc | 67 |
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 */ } |