#include "ardour/process_thread.h"
#include "ardour/audioengine.h"
-#include <jack/thread.h>
-
#include "i18n.h"
using namespace ARDOUR;
Graph::Graph (Session & session)
: SessionHandleRef (session)
- , _quit_threads (false)
+ , _threads_active (false)
, _execution_sem ("graph_execution", 0)
, _callback_start_sem ("graph_start", 0)
, _callback_done_sem ("graph_done", 0)
_current_chain = 0;
_pending_chain = 0;
_setup_chain = 1;
- _quit_threads = false;
_graph_empty = true;
+
+ ARDOUR::AudioEngine::instance()->Running.connect_same_thread (engine_connections, boost::bind (&Graph::reset_thread_list, this));
+ ARDOUR::AudioEngine::instance()->Stopped.connect_same_thread (engine_connections, boost::bind (&Graph::engine_stopped, this));
+ ARDOUR::AudioEngine::instance()->Halted.connect_same_thread (engine_connections, boost::bind (&Graph::engine_stopped, this));
+
reset_thread_list ();
#ifdef DEBUG_RT_ALLOC
#endif
}
+void
+Graph::engine_stopped ()
+{
+ if (AudioEngine::instance()->process_thread_count() != 0) {
+ drop_threads ();
+ }
+}
+
/** Set up threads for running the graph */
void
Graph::reset_thread_list ()
number of threads.
*/
- if (_thread_list.size() == num_threads) {
+ if (AudioEngine::instance()->process_thread_count() == num_threads) {
return;
}
Glib::Threads::Mutex::Lock lm (_session.engine().process_lock());
- jack_native_thread_t a_thread;
- if (!_thread_list.empty()) {
+ if (AudioEngine::instance()->process_thread_count() != 0) {
drop_threads ();
}
- if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this), &a_thread, 100000) != 0) {
+ _threads_active = true;
+
+ if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this)) != 0) {
throw failed_constructor ();
}
- _thread_list.push_back (a_thread);
-
for (uint32_t i = 1; i < num_threads; ++i) {
- if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this), &a_thread, 100000) != 0) {
+ if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this))) {
throw failed_constructor ();
}
-
- _thread_list.push_back (a_thread);
}
}
void
Graph::drop_threads ()
{
- _quit_threads = true;
+ Glib::Threads::Mutex::Lock ls (_swap_mutex);
+ _threads_active = false;
+
+ uint32_t thread_count = AudioEngine::instance()->process_thread_count ();
- for (unsigned int i=0; i< _thread_list.size(); i++) {
+ for (unsigned int i=0; i < thread_count; i++) {
+ pthread_mutex_lock (&_trigger_mutex);
_execution_sem.signal ();
+ pthread_mutex_unlock (&_trigger_mutex);
}
+ pthread_mutex_lock (&_trigger_mutex);
_callback_start_sem.signal ();
+ pthread_mutex_unlock (&_trigger_mutex);
- for (list<jack_native_thread_t>::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) {
- AudioEngine::instance()->stop_process_thread(*i);
- }
-
- _thread_list.clear ();
+ AudioEngine::instance()->join_process_threads ();
_execution_tokens = 0;
-
- _quit_threads = false;
}
void
void
Graph::dec_ref()
{
- if (g_atomic_int_dec_and_test (&_finished_refcount)) {
+ if (g_atomic_int_dec_and_test (const_cast<gint*> (&_finished_refcount))) {
/* We have run all the nodes that are at the `output' end of
the graph, so there is nothing more to do this time around.
/* Block until the a process callback triggers us */
_callback_start_sem.wait();
- if (_quit_threads) {
+ if (!_threads_active) {
return;
}
prep ();
- if (_graph_empty) {
+ if (_graph_empty && _threads_active) {
goto again;
}
pthread_mutex_unlock (&_trigger_mutex);
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 goes to sleep\n", pthread_name()));
_execution_sem.wait ();
- if (_quit_threads) {
+ if (!_threads_active) {
return true;
}
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("%1 is awake\n", pthread_name()));
DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("%1 has finished run_one()\n", pthread_name()));
- return false;
+ return !_threads_active;
}
void
DEBUG_TRACE(DEBUG::ProcessThreads, "main thread is awake\n");
- if (_quit_threads) {
+ if (!_threads_active) {
return;
}
prep ();
- if (_graph_empty && !_quit_threads) {
+ if (_graph_empty && _threads_active) {
_callback_done_sem.signal ();
DEBUG_TRACE(DEBUG::ProcessThreads, "main thread sees graph done, goes back to sleep\n");
goto again;
}
pt->drop_buffers();
+ delete (pt);
}
void
int
Graph::silent_process_routes (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool& need_butler)
{
+ if (!_threads_active) return 0;
+
_process_nframes = nframes;
_process_start_frame = start_frame;
_process_end_frame = end_frame;
{
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("graph execution from %1 to %2 = %3\n", start_frame, end_frame, nframes));
+ if (!_threads_active) return 0;
+
_process_nframes = nframes;
_process_start_frame = start_frame;
_process_end_frame = end_frame;
{
DEBUG_TRACE (DEBUG::ProcessThreads, string_compose ("no-roll graph execution from %1 to %2 = %3\n", start_frame, end_frame, nframes));
+ if (!_threads_active) return 0;
+
_process_nframes = nframes;
_process_start_frame = start_frame;
_process_end_frame = end_frame;
bool
Graph::in_process_thread () const
{
-#ifndef WIN32
- for (list<pthread_t>::const_iterator i = _thread_list.begin (); i != _thread_list.end(); ++i) {
- if (*i == pthread_self()) {
- return true;
- }
- }
- return false;
-#endif
+ return AudioEngine::instance()->in_process_thread ();
}