From eb10d32d8b59f2158ba64ba55e310ba0f5f24170 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 14 May 2008 23:31:15 +0000 Subject: Fix clear patch command (ticket #18). Potential destruction race/leak fixes. More thorough thread assertions on graph object methods. git-svn-id: http://svn.drobilla.net/lad/ingen@1207 a436a847-0d15-0410-975c-d299462d15a1 --- src/libs/engine/events/ClearPatchEvent.cpp | 75 +++++++++++++++++------------- src/libs/engine/events/ClearPatchEvent.hpp | 16 +++++-- src/libs/engine/events/DestroyEvent.cpp | 3 +- src/libs/engine/events/DestroyEvent.hpp | 3 +- 4 files changed, 59 insertions(+), 38 deletions(-) (limited to 'src/libs/engine/events') diff --git a/src/libs/engine/events/ClearPatchEvent.cpp b/src/libs/engine/events/ClearPatchEvent.cpp index 211ca79e..0e725e65 100644 --- a/src/libs/engine/events/ClearPatchEvent.cpp +++ b/src/libs/engine/events/ClearPatchEvent.cpp @@ -27,15 +27,19 @@ #include "NodeImpl.hpp" #include "ConnectionImpl.hpp" #include "QueuedEventSource.hpp" +#include "AudioDriver.hpp" +#include "MidiDriver.hpp" namespace Ingen { ClearPatchEvent::ClearPatchEvent(Engine& engine, SharedPtr responder, FrameTime time, QueuedEventSource* source, const string& patch_path) -: QueuedEvent(engine, responder, time, true, source), - _patch_path(patch_path), - _patch(NULL), - _process(false) + : QueuedEvent(engine, responder, time, true, source) + , _patch_path(patch_path) + , _driver_port(NULL) + , _process(false) + , _ports_array(NULL) + , _compiled_patch(NULL) { } @@ -43,18 +47,20 @@ ClearPatchEvent::ClearPatchEvent(Engine& engine, SharedPtr responder, void ClearPatchEvent::pre_process() { - cerr << "FIXME: CLEAR PATCH\n"; -#if 0 - _patch = _engine.object_store()->find_patch(_patch_path); + ObjectStore::Objects::iterator patch_iterator = _engine.object_store()->find(_patch_path); - if (_patch != NULL) { - - _process = _patch->enabled(); - - for (List::const_iterator i = _patch->nodes().begin(); i != _patch->nodes().end(); ++i) - (*i)->remove_from_store(); + if (patch_iterator != _engine.object_store()->objects().end()) { + _patch = PtrCast(patch_iterator->second); + if (_patch) { + _process = _patch->enabled(); + _removed_table = _engine.object_store()->remove_children(patch_iterator); + _patch->nodes().clear(); + _patch->connections().clear(); + _ports_array = _patch->build_ports_array(); + if (_patch->enabled()) + _compiled_patch = _patch->compile(); + } } -#endif QueuedEvent::pre_process(); } @@ -65,17 +71,31 @@ ClearPatchEvent::execute(ProcessContext& context) { QueuedEvent::execute(context); - if (_patch != NULL) { + if (_patch && _removed_table) { _patch->disable(); - cerr << "FIXME: CLEAR PATCH\n"; - //for (List::const_iterator i = _patch->nodes().begin(); i != _patch->nodes().end(); ++i) - // (*i)->remove_from_patch(); - if (_patch->compiled_patch() != NULL) { _engine.maid()->push(_patch->compiled_patch()); _patch->compiled_patch(NULL); } + + _patch->clear_ports(); + _patch->connections().clear(); + _patch->compiled_patch(_compiled_patch); + Raul::Array* old_ports = _patch->external_ports(); + _patch->external_ports(_ports_array); + _ports_array = old_ports; + + // Remove driver ports, if necessary + if (_patch->parent() == NULL) { + for (ObjectStore::Objects::iterator i = _removed_table->begin(); i != _removed_table->end(); ++i) { + SharedPtr port = PtrCast(i->second); + if (port && port->type() == DataType::AUDIO) + _driver_port = _engine.audio_driver()->remove_port(port->path()); + else if (port && port->type() == DataType::EVENT) + _driver_port = _engine.midi_driver()->remove_port(port->path()); + } + } } } @@ -84,18 +104,8 @@ void ClearPatchEvent::post_process() { if (_patch != NULL) { - // Delete all nodes - for (List::iterator i = _patch->nodes().begin(); i != _patch->nodes().end(); ++i) { - (*i)->deactivate(); - delete *i; - } - _patch->nodes().clear(); - - // Delete all connections - for (PatchImpl::Connections::iterator i = _patch->connections().begin(); i != _patch->connections().end(); ++i) - (*i).reset(); - - _patch->connections().clear(); + delete _ports_array; + delete _driver_port; // Restore patch's run state if (_process) @@ -105,8 +115,9 @@ ClearPatchEvent::post_process() // Make sure everything's sane assert(_patch->nodes().size() == 0); + assert(_patch->num_ports() == 0); assert(_patch->connections().size() == 0); - + // Reply _responder->respond_ok(); _engine.broadcaster()->send_patch_cleared(_patch_path); diff --git a/src/libs/engine/events/ClearPatchEvent.hpp b/src/libs/engine/events/ClearPatchEvent.hpp index afe66eed..0353dc01 100644 --- a/src/libs/engine/events/ClearPatchEvent.hpp +++ b/src/libs/engine/events/ClearPatchEvent.hpp @@ -20,13 +20,18 @@ #include #include +#include +#include #include "QueuedEvent.hpp" +#include "ObjectStore.hpp" +#include "PatchImpl.hpp" using std::string; namespace Ingen { class PatchImpl; +class DriverPort; /** Delete all nodes from a patch. @@ -43,9 +48,14 @@ public: void post_process(); private: - const string _patch_path; - PatchImpl* _patch; - bool _process; + const string _patch_path; + SharedPtr _patch; + DriverPort* _driver_port; + bool _process; + Raul::Array* _ports_array; ///< New (external) ports for Patch + CompiledPatch* _compiled_patch; ///< Patch's new process order + + SharedPtr< Table > > _removed_table; }; diff --git a/src/libs/engine/events/DestroyEvent.cpp b/src/libs/engine/events/DestroyEvent.cpp index d2b2d42b..4f2cba3f 100644 --- a/src/libs/engine/events/DestroyEvent.cpp +++ b/src/libs/engine/events/DestroyEvent.cpp @@ -199,8 +199,7 @@ DestroyEvent::post_process() _responder->respond_error("Unable to destroy object"); } - if (_driver_port) - delete _driver_port; + delete _driver_port; } diff --git a/src/libs/engine/events/DestroyEvent.hpp b/src/libs/engine/events/DestroyEvent.hpp index 4a82c5bb..134290b1 100644 --- a/src/libs/engine/events/DestroyEvent.hpp +++ b/src/libs/engine/events/DestroyEvent.hpp @@ -60,7 +60,6 @@ public: private: Path _path; ObjectStore::Objects::iterator _store_iterator; - SharedPtr< Table > > _removed_table; SharedPtr _node; ///< Non-NULL iff a node SharedPtr _port; ///< Non-NULL iff a port DriverPort* _driver_port; @@ -70,6 +69,8 @@ private: CompiledPatch* _compiled_patch; ///< Patch's new process order DisconnectNodeEvent* _disconnect_node_event; DisconnectPortEvent* _disconnect_port_event; + + SharedPtr< Table > > _removed_table; }; -- cgit v1.2.1