diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h index 3d65af481d..0e39625e8c 100644 --- a/libs/ardour/ardour/audio_backend.h +++ b/libs/ardour/ardour/audio_backend.h @@ -399,18 +399,26 @@ class AudioBackend : public PortEngine { * stacksize. The thread will begin executing @param func, and will exit * when that function returns. */ - virtual int create_process_thread (boost::function func, AudioBackendThread*, size_t stacksize) = 0; + virtual int create_process_thread (boost::function func) = 0; - /** Wait for the thread specified by @param thread to exit. + /** Wait for all processing threads to exit. * * Return zero on success, non-zero on failure. */ - virtual int join_process_thread (AudioBackendThread* thread) = 0; + virtual int join_process_threads () = 0; /** Return true if execution context is in a backend thread */ virtual bool in_process_thread () = 0; + /** Return the minimum stack size of audio threads in bytes + */ + static size_t thread_stack_size () { return 100000; } + + /** Return number of processing threads + */ + virtual uint32_t process_thread_count () = 0; + virtual void update_latencies () = 0; protected: diff --git a/libs/ardour/ardour/audio_backend_thread.h b/libs/ardour/ardour/audio_backend_thread.h deleted file mode 100644 index 90efecbc94..0000000000 --- a/libs/ardour/ardour/audio_backend_thread.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (C) 2013 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -namespace ARDOUR { - -class AudioBackendThread -{ -public: - - AudioBackendThread () { } - - virtual ~AudioBackendThread () { } - -}; - -} // namespace ARDOUR diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 82364ca191..1bf4be3243 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -58,7 +58,6 @@ class Session; class ProcessThread; class AudioBackend; class AudioBackendInfo; -class AudioBackendThread; class AudioEngine : public SessionHandlePtr, public PortManager { @@ -102,10 +101,10 @@ public: pframes_t samples_since_cycle_start (); bool get_sync_offset (pframes_t& offset) const; - int create_process_thread (boost::function func, AudioBackendThread*, size_t stacksize); - int join_process_thread (AudioBackendThread*); - + int create_process_thread (boost::function func); + int join_process_threads (); bool in_process_thread (); + uint32_t process_thread_count (); bool is_realtime() const; bool connected() const; diff --git a/libs/ardour/ardour/graph.h b/libs/ardour/ardour/graph.h index ed9e22de31..763723c792 100644 --- a/libs/ardour/ardour/graph.h +++ b/libs/ardour/ardour/graph.h @@ -47,8 +47,6 @@ class Route; class Session; class GraphEdges; -class AudioBackendThread; - typedef boost::shared_ptr node_ptr_t; typedef std::list< node_ptr_t > node_list_t; @@ -59,8 +57,6 @@ class Graph : public SessionHandleRef public: Graph (Session & session); - uint32_t threads_in_use () const { return _thread_list.size(); } - void prep(); void trigger (GraphNode * n); void rechain (boost::shared_ptr, GraphEdges const &); @@ -93,7 +89,6 @@ protected: virtual void session_going_away (); private: - std::list _thread_list; volatile bool _quit_threads; void reset_thread_list (); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 38e9ad0b86..631a861741 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -826,21 +826,21 @@ AudioEngine::get_sync_offset (pframes_t& offset) const } int -AudioEngine::create_process_thread (boost::function func, AudioBackendThread* thread, size_t stacksize) +AudioEngine::create_process_thread (boost::function func) { if (!_backend) { return -1; } - return _backend->create_process_thread (func, thread, stacksize); + return _backend->create_process_thread (func); } int -AudioEngine::join_process_thread (AudioBackendThread* thr) +AudioEngine::join_process_threads () { if (!_backend) { return -1; } - return _backend->join_process_thread (thr); + return _backend->join_process_threads (); } bool @@ -852,6 +852,15 @@ AudioEngine::in_process_thread () return _backend->in_process_thread (); } +uint32_t +AudioEngine::process_thread_count () +{ + if (!_backend) { + return 0; + } + return _backend->process_thread_count (); +} + int AudioEngine::set_device_name (const std::string& name) { diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc index 8b3d24031b..71eeee41ea 100644 --- a/libs/ardour/graph.cc +++ b/libs/ardour/graph.cc @@ -96,29 +96,24 @@ 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()); - AudioBackendThread* backend_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), backend_thread, 100000) != 0) { + if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this)) != 0) { throw failed_constructor (); } - _thread_list.push_back (backend_thread); - for (uint32_t i = 1; i < num_threads; ++i) { - if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this), backend_thread, 100000) != 0) { + if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this))) { throw failed_constructor (); } - - _thread_list.push_back (backend_thread); } } @@ -140,17 +135,15 @@ Graph::drop_threads () { _quit_threads = true; - 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++) { _execution_sem.signal (); } _callback_start_sem.signal (); - for (list::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) { - AudioEngine::instance()->join_process_thread (*i); - } - - _thread_list.clear (); + AudioEngine::instance()->join_process_threads (); _execution_tokens = 0; diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc index cd4874e85a..19f15b1fa1 100644 --- a/libs/backends/jack/jack_audiobackend.cc +++ b/libs/backends/jack/jack_audiobackend.cc @@ -33,7 +33,6 @@ #include "ardour/audioengine.h" #include "ardour/session.h" #include "ardour/types.h" -#include "ardour/audio_backend_thread.h" #include "jack_audiobackend.h" #include "jack_connection.h" @@ -46,16 +45,6 @@ using namespace PBD; using std::string; using std::vector; -class JACKAudioBackendThread : public AudioBackendThread -{ -public: - - JACKAudioBackendThread (jack_native_thread_t id) - : thread_id(id) { } - - jack_native_thread_t thread_id; - -}; #define GET_PRIVATE_JACK_POINTER(localvar) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; } #define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; } @@ -837,40 +826,45 @@ JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* ar } int -JACKAudioBackend::create_process_thread (boost::function f, AudioBackendThread* backend_thread, size_t stacksize) +JACKAudioBackend::create_process_thread (boost::function f) { GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); jack_native_thread_t thread_id; - ThreadData* td = new ThreadData (this, f, stacksize); + ThreadData* td = new ThreadData (this, f, thread_stack_size()); if (jack_client_create_thread (_priv_jack, &thread_id, jack_client_real_time_priority (_priv_jack), jack_is_realtime (_priv_jack), _start_process_thread, td)) { return -1; } - backend_thread = new JACKAudioBackendThread(thread_id); + _jack_threads.push_back(thread_id); return 0; } int -JACKAudioBackend::join_process_thread (AudioBackendThread* backend_thread) +JACKAudioBackend::join_process_threads () { GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); - JACKAudioBackendThread * jack_thread = dynamic_cast(backend_thread); int ret = 0; + for (std::vector::const_iterator i = _jack_threads.begin (); + i != _jack_threads.end(); i++) { + #if defined(USING_JACK2_EXPANSION_OF_JACK_API) || defined(PLATFORM_WINDOWS) - if (jack_client_stop_thread (_priv_jack, jack_thread->thread_id) != 0) { - error << "AudioEngine: cannot stop process thread" << endmsg; - ret = -1; - } + if (jack_client_stop_thread (_priv_jack, *i) != 0) { #else - void* status; - ret = pthread_join (jack_thread->thread_id, &status); + void* status; + if (pthread_join (*i, &status) != 0) { #endif - delete jack_thread; + error << "AudioEngine: cannot stop process thread" << endmsg; + ret += -1; + } + } + + _jack_threads.clear(); + return ret; } @@ -882,6 +876,12 @@ JACKAudioBackend::in_process_thread () return false; } +uint32_t +JACKAudioBackend::process_thread_count () +{ + return _jack_threads.size(); +} + void* JACKAudioBackend::_start_process_thread (void* arg) { diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h index 822dc71053..b8d8b3b3f1 100644 --- a/libs/backends/jack/jack_audiobackend.h +++ b/libs/backends/jack/jack_audiobackend.h @@ -103,9 +103,10 @@ class JACKAudioBackend : public AudioBackend { size_t raw_buffer_size (DataType t); - int create_process_thread (boost::function func, AudioBackendThread*, size_t stacksize); - int join_process_thread (AudioBackendThread*); + int create_process_thread (boost::function func); + int join_process_threads (); bool in_process_thread (); + uint32_t process_thread_count (); void transport_start (); void transport_stop (); @@ -185,6 +186,8 @@ class JACKAudioBackend : public AudioBackend { bool _freewheeling; std::map _raw_buffer_sizes; + std::vector _jack_threads; + static int _xrun_callback (void *arg); static void* _process_thread (void *arg); static int _sample_rate_callback (pframes_t nframes, void *arg);