Use dedicated thread to start export timespans #9798
This addresses an issue with creating a one-shot thread directly from the realtime callback, which can be problematic on Windows.
This commit is contained in:
parent
d8e4e7b259
commit
3751d20ce9
@ -146,7 +146,13 @@ class LIBARDOUR_API ExportHandler : public ExportElementFactory, public sigc::tr
|
|||||||
|
|
||||||
/* Timespan management */
|
/* Timespan management */
|
||||||
|
|
||||||
static void* start_timespan_bg (void*);
|
void timespan_thread_wakeup ();
|
||||||
|
|
||||||
|
static void* _timespan_thread_run (void*);
|
||||||
|
pthread_t _timespan_thread;
|
||||||
|
std::atomic<int> _timespan_thread_active;
|
||||||
|
pthread_mutex_t _timespan_mutex;
|
||||||
|
pthread_cond_t _timespan_cond;
|
||||||
|
|
||||||
int start_timespan ();
|
int start_timespan ();
|
||||||
int process_timespan (samplecnt_t samples);
|
int process_timespan (samplecnt_t samples);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "pbd/gstdio_compat.h"
|
#include "pbd/gstdio_compat.h"
|
||||||
#include <glibmm.h>
|
#include <glibmm.h>
|
||||||
#include <glibmm/convert.h>
|
#include <glibmm/convert.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "pbd/convert.h"
|
#include "pbd/convert.h"
|
||||||
|
|
||||||
@ -121,6 +122,12 @@ ExportHandler::ExportHandler (Session & session)
|
|||||||
, cue_tracknum (0)
|
, cue_tracknum (0)
|
||||||
, cue_indexnum (0)
|
, cue_indexnum (0)
|
||||||
{
|
{
|
||||||
|
pthread_mutex_init (&_timespan_mutex, 0);
|
||||||
|
pthread_cond_init (&_timespan_cond, 0);
|
||||||
|
_timespan_thread_active.store (1);
|
||||||
|
if (pthread_create (&_timespan_thread, NULL, _timespan_thread_run, this)) {
|
||||||
|
_timespan_thread_active.store (0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExportHandler::~ExportHandler ()
|
ExportHandler::~ExportHandler ()
|
||||||
@ -130,6 +137,56 @@ ExportHandler::~ExportHandler ()
|
|||||||
session.surround_master ()->surround_return ()->finalize_export ();
|
session.surround_master ()->surround_return ()->finalize_export ();
|
||||||
}
|
}
|
||||||
graph_builder->cleanup (export_status->aborted () );
|
graph_builder->cleanup (export_status->aborted () );
|
||||||
|
|
||||||
|
pthread_mutex_lock (&_timespan_mutex);
|
||||||
|
_timespan_thread_active.store (0);
|
||||||
|
pthread_cond_signal (&_timespan_cond);
|
||||||
|
pthread_mutex_unlock (&_timespan_mutex);
|
||||||
|
|
||||||
|
void *status;
|
||||||
|
pthread_join (_timespan_thread, &status);
|
||||||
|
|
||||||
|
pthread_cond_destroy (&_timespan_cond);
|
||||||
|
pthread_mutex_destroy (&_timespan_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
ExportHandler::_timespan_thread_run (void* me)
|
||||||
|
{
|
||||||
|
char name[64];
|
||||||
|
snprintf (name, 64, "Export-TS-%p", (void*)DEBUG_THREAD_SELF);
|
||||||
|
pthread_set_name (name);
|
||||||
|
ExportHandler* self = static_cast<ExportHandler*> (me);
|
||||||
|
|
||||||
|
SessionEvent::create_per_thread_pool (name, 512);
|
||||||
|
PBD::notify_event_loops_about_thread_creation (pthread_self(), name, 512);
|
||||||
|
|
||||||
|
pthread_mutex_lock (&self->_timespan_mutex);
|
||||||
|
while (self->_timespan_thread_active.load ()) {
|
||||||
|
pthread_cond_wait (&self->_timespan_cond, &self->_timespan_mutex);
|
||||||
|
if (!self->_timespan_thread_active.load ()) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
Temporal::TempoMap::fetch ();
|
||||||
|
self->process_connection.disconnect ();
|
||||||
|
Glib::Threads::Mutex::Lock l (self->export_status->lock());
|
||||||
|
DiskReader::allocate_working_buffers ();
|
||||||
|
self->start_timespan ();
|
||||||
|
DiskReader::free_working_buffers ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock (&self->_timespan_mutex);
|
||||||
|
pthread_exit (0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ExportHandler::timespan_thread_wakeup ()
|
||||||
|
{
|
||||||
|
if (pthread_mutex_trylock (&_timespan_mutex) == 0) {
|
||||||
|
pthread_cond_signal (&_timespan_cond);
|
||||||
|
pthread_mutex_unlock (&_timespan_mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Add an export to the `to-do' list */
|
/** Add an export to the `to-do' list */
|
||||||
@ -372,22 +429,6 @@ ExportHandler::command_output(std::string output, size_t size)
|
|||||||
info << output << endmsg;
|
info << output << endmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
|
||||||
ExportHandler::start_timespan_bg (void* eh)
|
|
||||||
{
|
|
||||||
char name[64];
|
|
||||||
snprintf (name, 64, "Export-TS-%p", (void*)DEBUG_THREAD_SELF);
|
|
||||||
pthread_set_name (name);
|
|
||||||
ExportHandler* self = static_cast<ExportHandler*> (eh);
|
|
||||||
self->process_connection.disconnect ();
|
|
||||||
Glib::Threads::Mutex::Lock l (self->export_status->lock());
|
|
||||||
SessionEvent::create_per_thread_pool (name, 512);
|
|
||||||
DiskReader::allocate_working_buffers ();
|
|
||||||
self->start_timespan ();
|
|
||||||
DiskReader::free_working_buffers ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ExportHandler::finish_timespan ()
|
ExportHandler::finish_timespan ()
|
||||||
{
|
{
|
||||||
@ -543,9 +584,7 @@ ExportHandler::finish_timespan ()
|
|||||||
/* finish timespan is called in freewheeling rt-context,
|
/* finish timespan is called in freewheeling rt-context,
|
||||||
* we cannot start a new export from here */
|
* we cannot start a new export from here */
|
||||||
assert (AudioEngine::instance()->freewheeling ());
|
assert (AudioEngine::instance()->freewheeling ());
|
||||||
pthread_t tid;
|
timespan_thread_wakeup ();
|
||||||
pthread_create (&tid, NULL, ExportHandler::start_timespan_bg, this);
|
|
||||||
pthread_detach (tid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user