From df363a4fb3057253c1530941176cac49a7ffd409 Mon Sep 17 00:00:00 2001 From: Tim Mayberry Date: Wed, 14 Aug 2013 20:30:09 +1000 Subject: [PATCH 1/3] Add AudioBackendThread class to support different thread type on windows --- libs/ardour/ardour/audio_backend.h | 8 +++- libs/ardour/ardour/audio_backend_thread.h | 32 +++++++++++++++ libs/ardour/ardour/audioengine.h | 9 ++++- libs/ardour/ardour/graph.h | 6 +-- libs/ardour/ardour/types.h | 10 ----- libs/ardour/audioengine.cc | 19 ++++++--- libs/ardour/graph.cc | 21 ++++------ libs/backends/jack/jack_audiobackend.cc | 48 ++++++++++++++++++++--- libs/backends/jack/jack_audiobackend.h | 5 ++- 9 files changed, 115 insertions(+), 43 deletions(-) create mode 100644 libs/ardour/ardour/audio_backend_thread.h diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h index 9052acd530..3d65af481d 100644 --- a/libs/ardour/ardour/audio_backend.h +++ b/libs/ardour/ardour/audio_backend.h @@ -399,13 +399,17 @@ 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, AudioBackendNativeThread*, size_t stacksize) = 0; + virtual int create_process_thread (boost::function func, AudioBackendThread*, size_t stacksize) = 0; /** Wait for the thread specified by @param thread to exit. * * Return zero on success, non-zero on failure. */ - virtual int wait_for_process_thread_exit (AudioBackendNativeThread thread) = 0; + virtual int join_process_thread (AudioBackendThread* thread) = 0; + + /** Return true if execution context is in a backend thread + */ + virtual bool in_process_thread () = 0; virtual void update_latencies () = 0; diff --git a/libs/ardour/ardour/audio_backend_thread.h b/libs/ardour/ardour/audio_backend_thread.h new file mode 100644 index 0000000000..90efecbc94 --- /dev/null +++ b/libs/ardour/ardour/audio_backend_thread.h @@ -0,0 +1,32 @@ +/* + 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 201d960479..82364ca191 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -58,6 +58,7 @@ class Session; class ProcessThread; class AudioBackend; class AudioBackendInfo; +class AudioBackendThread; class AudioEngine : public SessionHandlePtr, public PortManager { @@ -100,8 +101,12 @@ public: pframes_t sample_time_at_cycle_start (); pframes_t samples_since_cycle_start (); bool get_sync_offset (pframes_t& offset) const; - int create_process_thread (boost::function func, AudioBackendNativeThread*, size_t stacksize); - int wait_for_process_thread_exit (AudioBackendNativeThread); + + int create_process_thread (boost::function func, AudioBackendThread*, size_t stacksize); + int join_process_thread (AudioBackendThread*); + + bool in_process_thread (); + bool is_realtime() const; bool connected() const; diff --git a/libs/ardour/ardour/graph.h b/libs/ardour/ardour/graph.h index 08af6fb721..ed9e22de31 100644 --- a/libs/ardour/ardour/graph.h +++ b/libs/ardour/ardour/graph.h @@ -31,8 +31,6 @@ #include #include -#include - #include "pbd/semutils.h" #include "ardour/types.h" @@ -49,6 +47,8 @@ class Route; class Session; class GraphEdges; +class AudioBackendThread; + typedef boost::shared_ptr node_ptr_t; typedef std::list< node_ptr_t > node_list_t; @@ -93,7 +93,7 @@ protected: virtual void session_going_away (); private: - std::list _thread_list; + std::list _thread_list; volatile bool _quit_threads; void reset_thread_list (); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 526a71c58b..ee43d1f30f 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -615,16 +615,6 @@ namespace ARDOUR { uint32_t max; //< samples }; -/* PLATFORM SPECIFIC #ifdef's here */ - - /** Define the native thread type used on the platform */ - typedef pthread_t AudioBackendNativeThread; - static inline bool self_thread_equal (AudioBackendNativeThread thr) { - return pthread_equal (thr, pthread_self()); - } - -/* PLATFORM SPECIFIC #endif's here */ - } // namespace ARDOUR diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 465f88de56..38e9ad0b86 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -826,21 +826,30 @@ AudioEngine::get_sync_offset (pframes_t& offset) const } int -AudioEngine::create_process_thread (boost::function func, AudioBackendNativeThread* thr, size_t stacksize) +AudioEngine::create_process_thread (boost::function func, AudioBackendThread* thread, size_t stacksize) { if (!_backend) { return -1; } - return _backend->create_process_thread (func, thr, stacksize); + return _backend->create_process_thread (func, thread, stacksize); } int -AudioEngine::wait_for_process_thread_exit (AudioBackendNativeThread thr) +AudioEngine::join_process_thread (AudioBackendThread* thr) { if (!_backend) { - return 0; + return -1; } - return _backend->wait_for_process_thread_exit (thr); + return _backend->join_process_thread (thr); +} + +bool +AudioEngine::in_process_thread () +{ + if (!_backend) { + return false; + } + return _backend->in_process_thread (); } int diff --git a/libs/ardour/graph.cc b/libs/ardour/graph.cc index c8e374cddc..8b3d24031b 100644 --- a/libs/ardour/graph.cc +++ b/libs/ardour/graph.cc @@ -101,24 +101,24 @@ Graph::reset_thread_list () } Glib::Threads::Mutex::Lock lm (_session.engine().process_lock()); - AudioBackendNativeThread a_thread; + AudioBackendThread* backend_thread; if (!_thread_list.empty()) { drop_threads (); } - if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this), &a_thread, 100000) != 0) { + if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::main_thread, this), backend_thread, 100000) != 0) { throw failed_constructor (); } - _thread_list.push_back (a_thread); + _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), &a_thread, 100000) != 0) { + if (AudioEngine::instance()->create_process_thread (boost::bind (&Graph::helper_thread, this), backend_thread, 100000) != 0) { throw failed_constructor (); } - _thread_list.push_back (a_thread); + _thread_list.push_back (backend_thread); } } @@ -146,8 +146,8 @@ Graph::drop_threads () _callback_start_sem.signal (); - for (list::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) { - AudioEngine::instance()->wait_for_process_thread_exit (*i); + for (list::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) { + AudioEngine::instance()->join_process_thread (*i); } _thread_list.clear (); @@ -583,10 +583,5 @@ Graph::process_one_route (Route* route) bool Graph::in_process_thread () const { - for (list::const_iterator i = _thread_list.begin (); i != _thread_list.end(); ++i) { - if (self_thread_equal (*i)) { - return true; - } - } - return false; + return AudioEngine::instance()->in_process_thread (); } diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc index c6a523f4d2..cd4874e85a 100644 --- a/libs/backends/jack/jack_audiobackend.cc +++ b/libs/backends/jack/jack_audiobackend.cc @@ -33,6 +33,7 @@ #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" @@ -45,6 +46,17 @@ 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; } @@ -825,25 +837,49 @@ JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* ar } int -JACKAudioBackend::create_process_thread (boost::function f, pthread_t* thread, size_t stacksize) +JACKAudioBackend::create_process_thread (boost::function f, AudioBackendThread* backend_thread, size_t stacksize) { GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); + + jack_native_thread_t thread_id; ThreadData* td = new ThreadData (this, f, stacksize); - if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack), + 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; } - return 0; + backend_thread = new JACKAudioBackendThread(thread_id); + return 0; } int -JACKAudioBackend::wait_for_process_thread_exit (AudioBackendNativeThread thr) +JACKAudioBackend::join_process_thread (AudioBackendThread* backend_thread) { + GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); + + JACKAudioBackendThread * jack_thread = dynamic_cast(backend_thread); + int ret = 0; + +#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; + } +#else void* status; - /* this doesn't actively try to stop the thread, it just waits till it exits */ - return pthread_join (thr, &status); + ret = pthread_join (jack_thread->thread_id, &status); +#endif + delete jack_thread; + return ret; +} + +bool +JACKAudioBackend::in_process_thread () +{ + // XXX TODO + + return false; } void* diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h index 9ab545f3ee..822dc71053 100644 --- a/libs/backends/jack/jack_audiobackend.h +++ b/libs/backends/jack/jack_audiobackend.h @@ -103,8 +103,9 @@ class JACKAudioBackend : public AudioBackend { size_t raw_buffer_size (DataType t); - int create_process_thread (boost::function func, AudioBackendNativeThread*, size_t stacksize); - int wait_for_process_thread_exit (AudioBackendNativeThread); + int create_process_thread (boost::function func, AudioBackendThread*, size_t stacksize); + int join_process_thread (AudioBackendThread*); + bool in_process_thread (); void transport_start (); void transport_stop (); From 53ad2d187ffb31edcb90f7db5799886ee1806586 Mon Sep 17 00:00:00 2001 From: Tim Mayberry Date: Wed, 2 Oct 2013 19:40:48 +1000 Subject: [PATCH 2/3] Move processing thread list from ARDOUR::Graph into AudioBackend implementation --- libs/ardour/ardour/audio_backend.h | 14 +++++-- libs/ardour/ardour/audio_backend_thread.h | 32 ---------------- libs/ardour/ardour/audioengine.h | 7 ++-- libs/ardour/ardour/graph.h | 5 --- libs/ardour/audioengine.cc | 17 +++++++-- libs/ardour/graph.cc | 23 ++++-------- libs/backends/jack/jack_audiobackend.cc | 46 +++++++++++------------ libs/backends/jack/jack_audiobackend.h | 7 +++- 8 files changed, 63 insertions(+), 88 deletions(-) delete mode 100644 libs/ardour/ardour/audio_backend_thread.h 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); From f3a22fb88027548aebe67107e70113950d72417a Mon Sep 17 00:00:00 2001 From: Tim Mayberry Date: Thu, 3 Oct 2013 19:38:58 +1000 Subject: [PATCH 3/3] Implement JACKAudioBackend::in_process_thread --- libs/backends/jack/jack_audiobackend.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc index 19f15b1fa1..a651f2522d 100644 --- a/libs/backends/jack/jack_audiobackend.cc +++ b/libs/backends/jack/jack_audiobackend.cc @@ -871,7 +871,19 @@ JACKAudioBackend::join_process_threads () bool JACKAudioBackend::in_process_thread () { - // XXX TODO + for (std::vector::const_iterator i = _jack_threads.begin (); + i != _jack_threads.end(); i++) { + +#ifdef COMPILER_MINGW + if (*i == GetCurrentThread()) { + return true; + } +#else // pthreads + if (pthread_equal (*i, pthread_self()) != 0) { + return true; + } +#endif + } return false; }