aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-03-22 05:20:44 +0000
committerDavid Robillard <d@drobilla.net>2007-03-22 05:20:44 +0000
commitfdbf857218f79a231ec49f249aa51d2d5336d071 (patch)
tree33d00adba1c2ddf42b5c0928a335a03f6e4e4ceb
parent61c123747f791633bb9b61a1c528d7fbb7d7bdd7 (diff)
downloadmachina-fdbf857218f79a231ec49f249aa51d2d5336d071.tar.gz
machina-fdbf857218f79a231ec49f249aa51d2d5336d071.tar.bz2
machina-fdbf857218f79a231ec49f249aa51d2d5336d071.zip
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
-rw-r--r--src/engine/Engine.cpp5
-rw-r--r--src/engine/Machine.cpp56
-rw-r--r--src/engine/machina/Machine.hpp7
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<Machine>
Engine::load_machine(const Glib::ustring& uri)
{
+ SharedPtr<Machine> old_machine = _driver->machine(); // Hold a reference to current machine..
+
SharedPtr<Machine> 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<Node> 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> 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> 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<Raul::MIDISink> sink, const SharedPtr<Node> 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<Raul::MIDISink> sink, const SharedPtr<Node> 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<Raul::MIDISink> sink, const SharedPtr<Node> node)
SharedPtr<Node> dst = (*s)->dst();
if (!dst->is_active())
- dst->enter(sink, _time);
+ enter_node(sink, dst);
}
-
}
}
@@ -125,6 +168,7 @@ Machine::exit_node(SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> 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<Node> earliest_node() const;
- void exit_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node>);
+ bool enter_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node);
+ void exit_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node>);
+
+ static const size_t MAX_ACTIVE_NODES = 128;
+ SharedPtr<Node> _active_nodes[MAX_ACTIVE_NODES];
WeakPtr<Raul::MIDISink> _sink;
bool _is_activated;
@@ -76,7 +80,6 @@ private:
Raul::BeatTime _time;
Nodes _nodes;
- //Raul::List<SharedPtr<LearnRequest> > _pending_learns;
SharedPtr<LearnRequest> _pending_learn;
};