From fdbf857218f79a231ec49f249aa51d2d5336d071 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 22 Mar 2007 05:20:44 +0000 Subject: Runtime (RT thread) performance improvements. Fixed crash on opening multiple machines. git-svn-id: http://svn.drobilla.net/lad/machina@370 a436a847-0d15-0410-975c-d299462d15a1 --- src/engine/Engine.cpp | 5 ++++ src/engine/Machine.cpp | 56 +++++++++++++++++++++++++++++++++++++----- src/engine/machina/Machine.hpp | 7 ++++-- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index fede33f..2b4088e 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -30,11 +30,16 @@ namespace Machina { SharedPtr Engine::load_machine(const Glib::ustring& uri) { + SharedPtr old_machine = _driver->machine(); // Hold a reference to current machine.. + SharedPtr m = Loader().load(uri); if (m) { m->activate(); _driver->set_machine(m); } + + // .. and drop it in this thread (to prevent deallocation in the RT thread) + return m; } diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp index 844d2ce..f2aa845 100644 --- a/src/engine/Machine.cpp +++ b/src/engine/Machine.cpp @@ -85,24 +85,68 @@ Machine::earliest_node() const { SharedPtr earliest; - for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { + for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { + const SharedPtr node = _active_nodes[i]; + + if (node) { + assert(node->is_active()); + if (!earliest || node->exit_time() < earliest->exit_time()) { + earliest = node; + } + } + } + /*for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { const SharedPtr node = (*n); if (node->is_active()) if (!earliest || node->exit_time() < earliest->exit_time()) earliest = node; - } + }*/ return earliest; } +/** Enter a state at the current _time. + * + * Returns true if node was entered, or false if the maximum active nodes has been reached. + */ +bool +Machine::enter_node(const SharedPtr sink, const SharedPtr node) +{ + assert(!node->is_active()); + + /* FIXME: Would be best to use the MIDI note here as a hash key, at least + * while all actions are still MIDI notes... */ + size_t index = (rand() % MAX_ACTIVE_NODES); + for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { + if (_active_nodes[index] == NULL) { + node->enter(sink, _time); + assert(node->is_active()); + _active_nodes[index] = node; + return true; + } + index = (index + 1) % MAX_ACTIVE_NODES; + } + + // If we get here, ran out of active node spots. Don't enter node + return false; +} + + + /** Exit an active node at the current _time. */ void Machine::exit_node(SharedPtr sink, const SharedPtr node) { node->exit(sink, _time); + assert(!node->is_active()); + for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { + if (_active_nodes[i] == node) { + _active_nodes[i].reset(); + } + } // Activate all successors to this node // (that aren't aready active right now) @@ -115,9 +159,8 @@ Machine::exit_node(SharedPtr sink, const SharedPtr node) SharedPtr dst = (*s)->dst(); if (!dst->is_active()) - dst->enter(sink, _time); + enter_node(sink, dst); } - } } @@ -125,6 +168,7 @@ Machine::exit_node(SharedPtr sink, const SharedPtr node) /** Run the machine for @a nframes frames. * * Returns the duration of time the machine actually ran (from 0 to nframes). + * * Caller can check is_finished() to determine if the machine still has any * active states. If not, time() will return the exact time stamp the * machine actually finished on (so it can be restarted immediately @@ -156,8 +200,8 @@ Machine::run(const Raul::TimeSlice& time) assert( ! (*n)->is_active()); if ((*n)->is_initial()) { - (*n)->enter(sink, 0); - entered = true; + if (enter_node(sink, (*n))) + entered = true; } } diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp index fb37f4e..b8e371d 100644 --- a/src/engine/machina/Machine.hpp +++ b/src/engine/machina/Machine.hpp @@ -68,7 +68,11 @@ private: // Audio context SharedPtr earliest_node() const; - void exit_node(const SharedPtr sink, const SharedPtr); + bool enter_node(const SharedPtr sink, const SharedPtr node); + void exit_node(const SharedPtr sink, const SharedPtr); + + static const size_t MAX_ACTIVE_NODES = 128; + SharedPtr _active_nodes[MAX_ACTIVE_NODES]; WeakPtr _sink; bool _is_activated; @@ -76,7 +80,6 @@ private: Raul::BeatTime _time; Nodes _nodes; - //Raul::List > _pending_learns; SharedPtr _pending_learn; }; -- cgit v1.2.1