summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/ardour/ardour/graph.h6
-rw-r--r--libs/ardour/ardour/graphnode.h1
-rw-r--r--libs/ardour/graph.cc19
-rw-r--r--libs/ardour/graphnode.cc11
4 files changed, 33 insertions, 4 deletions
diff --git a/libs/ardour/ardour/graph.h b/libs/ardour/ardour/graph.h
index 18a8c7a4c9..14ef353853 100644
--- a/libs/ardour/ardour/graph.h
+++ b/libs/ardour/ardour/graph.h
@@ -108,12 +108,16 @@ private:
PBD::ProcessSemaphore _execution_sem;
+ /** Signalled to start a run of the graph for a process callback */
PBD::ProcessSemaphore _callback_start_sem;
PBD::ProcessSemaphore _callback_done_sem;
PBD::ProcessSemaphore _cleanup_sem;
+ /** The number of processing threads that are asleep */
volatile gint _execution_tokens;
+ /** The number of unprocessed nodes that do not feed any other node; updated during processing */
volatile gint _finished_refcount;
+ /** The initial number of nodes that do not feed any other node (for each chain) */
volatile gint _init_finished_refcount[2];
bool _graph_empty;
@@ -135,7 +139,7 @@ private:
bool _process_silent;
bool _process_noroll;
- int _process_retval;
+ int _process_retval;
bool _process_need_butler;
};
diff --git a/libs/ardour/ardour/graphnode.h b/libs/ardour/ardour/graphnode.h
index 191babdb12..9e0182300f 100644
--- a/libs/ardour/ardour/graphnode.h
+++ b/libs/ardour/ardour/graphnode.h
@@ -53,6 +53,7 @@ class GraphNode
private:
friend class Graph;
+ /** Nodes that we directly feed */
node_set_t _activation_set[2];
boost::shared_ptr<Graph> _graph;
diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc
index 0950ee28c0..9dfc611e17 100644
--- a/libs/ardour/graph.cc
+++ b/libs/ardour/graph.cc
@@ -93,6 +93,7 @@ Graph::parameter_changed (std::string param)
}
}
+/** Set up threads for running the graph */
void
Graph::reset_thread_list ()
{
@@ -220,6 +221,7 @@ Graph::prep()
}
_finished_refcount = _init_finished_refcount[chain];
+ /* Trigger the initial nodes for processing, which are the ones at the `input' end */
for (i=_init_trigger_list[chain].begin(); i!=_init_trigger_list[chain].end(); i++) {
this->trigger( i->get() );
}
@@ -233,6 +235,9 @@ Graph::trigger (GraphNode* n)
pthread_mutex_unlock (&_trigger_mutex);
}
+/** Called when a node at the `output' end of the chain (ie one that has no-one to feed)
+ * is finished.
+ */
void
Graph::dec_ref()
{
@@ -254,7 +259,7 @@ Graph::restart_cycle()
again:
_callback_done_sem.signal ();
- // block until we are triggered.
+ /* Block until the a process callback triggers us */
_callback_start_sem.wait();
if (_quit_threads) {
@@ -383,6 +388,9 @@ Graph::rechain (boost::shared_ptr<RouteList> routelist)
dump(chain);
}
+/** Called by both the main thread and all helpers.
+ * @return true to quit, false to carry on.
+ */
bool
Graph::run_one()
{
@@ -396,10 +404,14 @@ Graph::run_one()
to_run = 0;
}
+ /* the number of threads that are asleep */
int et = _execution_tokens;
+ /* the number of nodes that need to be run */
int ts = _trigger_queue.size();
+ /* hence how many threads to wake up */
int wakeup = min (et, ts);
+ /* update the number of threads that will still be sleeping */
_execution_tokens -= wakeup;
DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("%1 signals %2\n", pthread_self(), wakeup));
@@ -470,6 +482,7 @@ Graph::helper_thread()
pt->drop_buffers();
}
+/** Here's the main graph thread */
void
Graph::main_thread()
{
@@ -482,6 +495,7 @@ Graph::main_thread()
again:
_callback_start_sem.wait ();
+
DEBUG_TRACE(DEBUG::ProcessThreads, "main thread is awake\n");
if (_quit_threads) {
@@ -492,10 +506,11 @@ Graph::main_thread()
if (_graph_empty && !_quit_threads) {
_callback_done_sem.signal ();
- DEBUG_TRACE(DEBUG::ProcessThreads, "main thread sees graph done, goes back to slee\n");
+ DEBUG_TRACE(DEBUG::ProcessThreads, "main thread sees graph done, goes back to sleep\n");
goto again;
}
+ /* This loop will run forever */
while (1) {
DEBUG_TRACE(DEBUG::ProcessThreads, "main thread runs one graph node\n");
if (run_one()) {
diff --git a/libs/ardour/graphnode.cc b/libs/ardour/graphnode.cc
index 72b64abae0..c8923a043d 100644
--- a/libs/ardour/graphnode.cc
+++ b/libs/ardour/graphnode.cc
@@ -36,14 +36,22 @@ GraphNode::~GraphNode()
void
GraphNode::prep (int chain)
{
+ /* This is the number of nodes that directly feed us */
_refcount = _init_refcount[chain];
}
+/** Called by another node to tell us that one of the nodes that feed us
+ * has been processed.
+ */
void
GraphNode::dec_ref()
{
- if (g_atomic_int_dec_and_test (&_refcount))
+ if (g_atomic_int_dec_and_test (&_refcount)) {
+ /* All the nodes that feed us are done, so we can queue this node
+ for processing.
+ */
_graph->trigger (this);
+ }
}
void
@@ -52,6 +60,7 @@ GraphNode::finish (int chain)
node_set_t::iterator i;
bool feeds_somebody = false;
+ /* Tell the nodes that we feed that we've finished */
for (i=_activation_set[chain].begin(); i!=_activation_set[chain].end(); i++) {
(*i)->dec_ref();
feeds_somebody = true;