mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-24 07:27:44 +01:00
Merge branch 'audiothreads' of https://github.com/mojofunk/ardour
This commit is contained in:
commit
2d5e605bf1
8 changed files with 114 additions and 55 deletions
|
|
@ -399,13 +399,25 @@ 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<void()> func, AudioBackendNativeThread*, size_t stacksize) = 0;
|
||||
virtual int create_process_thread (boost::function<void()> 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 wait_for_process_thread_exit (AudioBackendNativeThread 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -100,8 +100,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<void()> func, AudioBackendNativeThread*, size_t stacksize);
|
||||
int wait_for_process_thread_exit (AudioBackendNativeThread);
|
||||
|
||||
int create_process_thread (boost::function<void()> func);
|
||||
int join_process_threads ();
|
||||
bool in_process_thread ();
|
||||
uint32_t process_thread_count ();
|
||||
|
||||
bool is_realtime() const;
|
||||
bool connected() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
#include <glib.h>
|
||||
#include <cassert>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "pbd/semutils.h"
|
||||
|
||||
#include "ardour/types.h"
|
||||
|
|
@ -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<RouteList>, GraphEdges const &);
|
||||
|
|
@ -93,7 +89,6 @@ protected:
|
|||
virtual void session_going_away ();
|
||||
|
||||
private:
|
||||
std::list<AudioBackendNativeThread> _thread_list;
|
||||
volatile bool _quit_threads;
|
||||
|
||||
void reset_thread_list ();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -826,21 +826,39 @@ AudioEngine::get_sync_offset (pframes_t& offset) const
|
|||
}
|
||||
|
||||
int
|
||||
AudioEngine::create_process_thread (boost::function<void()> func, AudioBackendNativeThread* thr, size_t stacksize)
|
||||
AudioEngine::create_process_thread (boost::function<void()> func)
|
||||
{
|
||||
if (!_backend) {
|
||||
return -1;
|
||||
}
|
||||
return _backend->create_process_thread (func, thr, stacksize);
|
||||
return _backend->create_process_thread (func);
|
||||
}
|
||||
|
||||
int
|
||||
AudioEngine::wait_for_process_thread_exit (AudioBackendNativeThread thr)
|
||||
AudioEngine::join_process_threads ()
|
||||
{
|
||||
if (!_backend) {
|
||||
return -1;
|
||||
}
|
||||
return _backend->join_process_threads ();
|
||||
}
|
||||
|
||||
bool
|
||||
AudioEngine::in_process_thread ()
|
||||
{
|
||||
if (!_backend) {
|
||||
return false;
|
||||
}
|
||||
return _backend->in_process_thread ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
AudioEngine::process_thread_count ()
|
||||
{
|
||||
if (!_backend) {
|
||||
return 0;
|
||||
}
|
||||
return _backend->wait_for_process_thread_exit (thr);
|
||||
return _backend->process_thread_count ();
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
AudioBackendNativeThread 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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<AudioBackendNativeThread>::iterator i = _thread_list.begin(); i != _thread_list.end(); ++i) {
|
||||
AudioEngine::instance()->wait_for_process_thread_exit (*i);
|
||||
}
|
||||
|
||||
_thread_list.clear ();
|
||||
AudioEngine::instance()->join_process_threads ();
|
||||
|
||||
_execution_tokens = 0;
|
||||
|
||||
|
|
@ -583,10 +576,5 @@ Graph::process_one_route (Route* route)
|
|||
bool
|
||||
Graph::in_process_thread () const
|
||||
{
|
||||
for (list<AudioBackendNativeThread>::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 ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ using namespace PBD;
|
|||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
|
||||
#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 +826,72 @@ JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* ar
|
|||
}
|
||||
|
||||
int
|
||||
JACKAudioBackend::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
|
||||
JACKAudioBackend::create_process_thread (boost::function<void()> f)
|
||||
{
|
||||
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
|
||||
ThreadData* td = new ThreadData (this, f, stacksize);
|
||||
|
||||
if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
|
||||
jack_native_thread_t thread_id;
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
_jack_threads.push_back(thread_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
JACKAudioBackend::wait_for_process_thread_exit (AudioBackendNativeThread thr)
|
||||
JACKAudioBackend::join_process_threads ()
|
||||
{
|
||||
void* status;
|
||||
/* this doesn't actively try to stop the thread, it just waits till it exits */
|
||||
return pthread_join (thr, &status);
|
||||
GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
|
||||
|
||||
int ret = 0;
|
||||
|
||||
for (std::vector<jack_native_thread_t>::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, *i) != 0) {
|
||||
#else
|
||||
void* status;
|
||||
if (pthread_join (*i, &status) != 0) {
|
||||
#endif
|
||||
error << "AudioEngine: cannot stop process thread" << endmsg;
|
||||
ret += -1;
|
||||
}
|
||||
}
|
||||
|
||||
_jack_threads.clear();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
JACKAudioBackend::in_process_thread ()
|
||||
{
|
||||
for (std::vector<jack_native_thread_t>::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;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
JACKAudioBackend::process_thread_count ()
|
||||
{
|
||||
return _jack_threads.size();
|
||||
}
|
||||
|
||||
void*
|
||||
|
|
|
|||
|
|
@ -103,8 +103,10 @@ class JACKAudioBackend : public AudioBackend {
|
|||
|
||||
size_t raw_buffer_size (DataType t);
|
||||
|
||||
int create_process_thread (boost::function<void()> func, AudioBackendNativeThread*, size_t stacksize);
|
||||
int wait_for_process_thread_exit (AudioBackendNativeThread);
|
||||
int create_process_thread (boost::function<void()> func);
|
||||
int join_process_threads ();
|
||||
bool in_process_thread ();
|
||||
uint32_t process_thread_count ();
|
||||
|
||||
void transport_start ();
|
||||
void transport_stop ();
|
||||
|
|
@ -184,6 +186,8 @@ class JACKAudioBackend : public AudioBackend {
|
|||
bool _freewheeling;
|
||||
std::map<DataType,size_t> _raw_buffer_sizes;
|
||||
|
||||
std::vector<jack_native_thread_t> _jack_threads;
|
||||
|
||||
static int _xrun_callback (void *arg);
|
||||
static void* _process_thread (void *arg);
|
||||
static int _sample_rate_callback (pframes_t nframes, void *arg);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue