triggerbox: more work on ringbuffer request queue for trigger thread

This commit is contained in:
Paul Davis 2021-11-09 22:36:51 -07:00
parent 38bf55a1fd
commit 431b7c0d4e
3 changed files with 71 additions and 44 deletions

View File

@ -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 {

View File

@ -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 ();

View File

@ -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);
} }