X-Git-Url: https://main.carlh.net/gitweb/?p=ardour.git;a=blobdiff_plain;f=libs%2Fardour%2Fgraph.cc;h=563c882efec76706c6b6c2032a10e343ecc56af9;hp=12752c158e91e0b54cbc0ba1c4ae9a9d87365c1d;hb=c8c6bca6587450ff64303dbc994a4cd28d6ce7aa;hpb=0aac62e013e15e380001dafae39d554f8765a4a1 diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc index 12752c158e..563c882efe 100644 --- a/libs/ardour/graph.cc +++ b/libs/ardour/graph.cc @@ -32,9 +32,7 @@ #include "ardour/process_thread.h" #include "ardour/audioengine.h" -#include - -#include "i18n.h" +#include "pbd/i18n.h" using namespace ARDOUR; using namespace PBD; @@ -55,7 +53,7 @@ int alloc_allowed () 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) @@ -73,9 +71,13 @@ Graph::Graph (Session & session) _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 @@ -84,6 +86,14 @@ Graph::Graph (Session & session) #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 () @@ -97,29 +107,26 @@ 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); } } @@ -139,23 +146,24 @@ Graph::session_going_away() void Graph::drop_threads () { - _quit_threads = true; + Glib::Threads::Mutex::Lock ls (_swap_mutex); + _threads_active = false; - for (unsigned int i=0; i< _thread_list.size(); i++) { + uint32_t thread_count = AudioEngine::instance()->process_thread_count (); + + 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::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 @@ -231,7 +239,7 @@ Graph::trigger (GraphNode* n) void Graph::dec_ref() { - if (g_atomic_int_dec_and_test (&_finished_refcount)) { + if (g_atomic_int_dec_and_test (const_cast (&_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. @@ -252,13 +260,13 @@ Graph::restart_cycle() /* 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; } @@ -377,7 +385,7 @@ Graph::run_one() 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())); @@ -394,7 +402,7 @@ Graph::run_one() DEBUG_TRACE(DEBUG::ProcessThreads, string_compose ("%1 has finished run_one()\n", pthread_name())); - return false; + return !_threads_active; } void @@ -404,15 +412,16 @@ Graph::helper_thread() ProcessThread* pt = new ProcessThread (); resume_rt_malloc_checks (); - pt->get_buffers(); + pt->get_buffers(); - while(1) { - if (run_one()) { - break; - } - } + while(1) { + if (run_one()) { + break; + } + } - pt->drop_buffers(); + pt->drop_buffers(); + delete pt; } /** Here's the main graph thread */ @@ -423,34 +432,35 @@ Graph::main_thread() ProcessThread* pt = new ProcessThread (); resume_rt_malloc_checks (); - pt->get_buffers(); + pt->get_buffers(); + +again: + _callback_start_sem.wait (); - again: - _callback_start_sem.wait (); - DEBUG_TRACE(DEBUG::ProcessThreads, "main thread is awake\n"); - if (_quit_threads) { - return; - } + if (!_threads_active) { + return; + } prep (); - if (_graph_empty && !_quit_threads) { - _callback_done_sem.signal (); - DEBUG_TRACE(DEBUG::ProcessThreads, "main thread sees graph done, goes back to sleep\n"); - goto again; - } + 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; + } /* This loop will run forever */ - while (1) { + while (1) { DEBUG_TRACE(DEBUG::ProcessThreads, "main thread runs one graph node\n"); - if (run_one()) { - break; - } - } + if (run_one()) { + break; + } + } - pt->drop_buffers(); + pt->drop_buffers(); + delete (pt); } void @@ -483,6 +493,8 @@ Graph::dump (int chain) 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; @@ -508,6 +520,8 @@ Graph::process_routes (pframes_t nframes, framepos_t start_frame, framepos_t end { 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; @@ -535,6 +549,8 @@ Graph::routes_no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end { 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; @@ -584,12 +600,5 @@ Graph::process_one_route (Route* route) bool Graph::in_process_thread () const { -#ifndef WIN32 - for (list::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 (); }