triggerbox: more work on ringbuffer request queue for trigger thread
This commit is contained in:
parent
38bf55a1fd
commit
431b7c0d4e
|
@ -339,35 +339,44 @@ class LIBARDOUR_API TriggerBoxThread
|
||||||
TriggerBoxThread ();
|
TriggerBoxThread ();
|
||||||
~TriggerBoxThread();
|
~TriggerBoxThread();
|
||||||
|
|
||||||
|
static void init_request_pool() { Request::init_pool(); }
|
||||||
|
|
||||||
|
enum RequestType {
|
||||||
|
Quit,
|
||||||
|
SetRegion
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_region (int32_t slot, boost::shared_ptr<Region>);
|
||||||
|
|
||||||
void summon();
|
void summon();
|
||||||
void stop();
|
void stop();
|
||||||
void wait_until_finished();
|
void wait_until_finished();
|
||||||
|
|
||||||
|
private:
|
||||||
static void* _thread_work(void *arg);
|
static void* _thread_work(void *arg);
|
||||||
void* thread_work();
|
void* thread_work();
|
||||||
|
|
||||||
struct Request {
|
struct Request {
|
||||||
enum Type {
|
|
||||||
Run,
|
Request (RequestType t) : type (t) {}
|
||||||
Pause,
|
|
||||||
Quit
|
RequestType type;
|
||||||
};
|
/* for set region */
|
||||||
|
int32_t slot;
|
||||||
|
boost::shared_ptr<Region> region;
|
||||||
|
|
||||||
|
void* operator new (size_t);
|
||||||
|
void operator delete (void* ptr, size_t);
|
||||||
|
|
||||||
|
static MultiAllocSingleReleasePool* pool;
|
||||||
|
static void init_pool ();
|
||||||
};
|
};
|
||||||
|
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
|
PBD::RingBuffer<Request*> requests;
|
||||||
Glib::Threads::Mutex request_lock;
|
|
||||||
Glib::Threads::Cond paused;
|
|
||||||
bool should_run;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add request to thread request queue
|
|
||||||
*/
|
|
||||||
void queue_request (Request::Type r);
|
|
||||||
|
|
||||||
CrossThreadChannel _xthread;
|
CrossThreadChannel _xthread;
|
||||||
|
void queue_request (Request*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -518,10 +527,10 @@ class LIBARDOUR_API TriggerBox : public Processor
|
||||||
|
|
||||||
void reload (BufferSet& bufs, int32_t slot, void* ptr);
|
void reload (BufferSet& bufs, int32_t slot, void* ptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Properties {
|
namespace Properties {
|
||||||
|
|
|
@ -552,6 +552,7 @@ ARDOUR::init (bool try_optimization, const char* localedir, bool with_gui)
|
||||||
SessionEvent::init_event_pool ();
|
SessionEvent::init_event_pool ();
|
||||||
TransportFSM::Event::init_pool ();
|
TransportFSM::Event::init_pool ();
|
||||||
TriggerBox::init_pool ();
|
TriggerBox::init_pool ();
|
||||||
|
TriggerBoxThread::init_request_pool ();
|
||||||
|
|
||||||
Operations::make_operations_quarks ();
|
Operations::make_operations_quarks ();
|
||||||
SessionObject::make_property_quarks ();
|
SessionObject::make_property_quarks ();
|
||||||
|
|
|
@ -2352,8 +2352,11 @@ TriggerBox::reload (BufferSet& bufs, int32_t slot, void* ptr)
|
||||||
|
|
||||||
/* Thread */
|
/* Thread */
|
||||||
|
|
||||||
|
MultiAllocSingleReleasePool* TriggerBoxThread::Request::pool = 0;
|
||||||
|
|
||||||
TriggerBoxThread::TriggerBoxThread ()
|
TriggerBoxThread::TriggerBoxThread ()
|
||||||
: _xthread (true)
|
: requests (1024)
|
||||||
|
, _xthread (true)
|
||||||
{
|
{
|
||||||
if (pthread_create_and_store ("triggerbox thread", &thread, _thread_work, this)) {
|
if (pthread_create_and_store ("triggerbox thread", &thread, _thread_work, this)) {
|
||||||
error << _("Session: could not create triggerbox thread") << endmsg;
|
error << _("Session: could not create triggerbox thread") << endmsg;
|
||||||
|
@ -2364,7 +2367,8 @@ TriggerBoxThread::TriggerBoxThread ()
|
||||||
TriggerBoxThread::~TriggerBoxThread()
|
TriggerBoxThread::~TriggerBoxThread()
|
||||||
{
|
{
|
||||||
void* status;
|
void* status;
|
||||||
queue_request (Request::Quit);
|
Request* q = new Request (Quit);
|
||||||
|
queue_request (q);
|
||||||
pthread_join (thread, &status);
|
pthread_join (thread, &status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2379,22 +2383,44 @@ TriggerBoxThread::_thread_work (void* arg)
|
||||||
void *
|
void *
|
||||||
TriggerBoxThread::thread_work ()
|
TriggerBoxThread::thread_work ()
|
||||||
{
|
{
|
||||||
uint32_t err = 0;
|
|
||||||
|
|
||||||
bool disk_work_outstanding = false;
|
|
||||||
RouteList::iterator i;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
|
char msg;
|
||||||
|
|
||||||
|
if (_xthread.receive (msg, true) >= 0) {
|
||||||
|
RequestType req = (RequestType) msg;
|
||||||
|
switch (req) {
|
||||||
|
case Quit:
|
||||||
|
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: tbthread asked to quit @ %2\n", DEBUG_THREAD_SELF, g_get_monotonic_time()));
|
||||||
|
return 0;
|
||||||
|
abort(); /*NOTREACHED*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* something woke us up. We'll check the
|
||||||
|
ringbuffer to see what needs doing
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Temporal::TempoMap::fetch ();
|
Temporal::TempoMap::fetch ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (void *) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TriggerBoxThread::queue_request (Request::Type r)
|
TriggerBoxThread::queue_request (Request* req)
|
||||||
{
|
{
|
||||||
char c = r;
|
char c = req->type;
|
||||||
|
|
||||||
|
if (req->type != Quit) {
|
||||||
|
if (requests.write (&req, 1) != 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (_xthread.deliver (c) != 1) {
|
if (_xthread.deliver (c) != 1) {
|
||||||
/* the x-thread channel is non-blocking
|
/* the x-thread channel is non-blocking
|
||||||
* write may fail, but we really don't want to wait
|
* write may fail, but we really don't want to wait
|
||||||
|
@ -2410,29 +2436,20 @@ TriggerBoxThread::queue_request (Request::Type r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void*
|
||||||
TriggerBoxThread::summon ()
|
TriggerBoxThread::Request::operator new (size_t)
|
||||||
{
|
{
|
||||||
// DEBUG_TRACE (DEBUG::TriggerBoxThread, string_compose ("%1: summon tbthread to run @ %2\n", DEBUG_THREAD_SELF, g_get_monotonic_time()));
|
return pool->alloc ();
|
||||||
queue_request (Request::Run);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TriggerBoxThread::stop ()
|
TriggerBoxThread::Request::operator delete (void* ptr, size_t)
|
||||||
{
|
{
|
||||||
Glib::Threads::Mutex::Lock lm (request_lock);
|
pool->release (ptr);
|
||||||
// DEBUG_TRACE (DEBUG::TriggerBoxThread, string_compose ("%1: asking tbthread to stop @ %2\n", DEBUG_THREAD_SELF, g_get_monotonic_time()));
|
|
||||||
queue_request (Request::Pause);
|
|
||||||
paused.wait(request_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TriggerBoxThread::wait_until_finished ()
|
TriggerBoxThread::Request::init_pool ()
|
||||||
{
|
{
|
||||||
Glib::Threads::Mutex::Lock lm (request_lock);
|
pool = new MultiAllocSingleReleasePool (X_("TriggerBoxThreadRequests"), sizeof (TriggerBoxThread::Request), 1024);
|
||||||
// DEBUG_TRACE (DEBUG::TriggerBoxThread, string_compose ("%1: waiting for tbthread to finish @ %2\n", DEBUG_THREAD_SELF, g_get_monotonic_time()));
|
|
||||||
queue_request (Request::Pause);
|
|
||||||
paused.wait(request_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user