diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 43b13d2764..ae11121402 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -339,35 +339,44 @@ class LIBARDOUR_API TriggerBoxThread TriggerBoxThread (); ~TriggerBoxThread(); + static void init_request_pool() { Request::init_pool(); } + + enum RequestType { + Quit, + SetRegion + }; + + void set_region (int32_t slot, boost::shared_ptr); + void summon(); void stop(); void wait_until_finished(); + private: static void* _thread_work(void *arg); void* thread_work(); struct Request { - enum Type { - Run, - Pause, - Quit - }; + + Request (RequestType t) : type (t) {} + + RequestType type; + /* for set region */ + int32_t slot; + boost::shared_ptr region; + + void* operator new (size_t); + void operator delete (void* ptr, size_t); + + static MultiAllocSingleReleasePool* pool; + static void init_pool (); }; pthread_t thread; - - 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); + PBD::RingBuffer requests; 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); - - + + }; namespace Properties { diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 9b0759a500..90585ad978 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -552,6 +552,7 @@ ARDOUR::init (bool try_optimization, const char* localedir, bool with_gui) SessionEvent::init_event_pool (); TransportFSM::Event::init_pool (); TriggerBox::init_pool (); + TriggerBoxThread::init_request_pool (); Operations::make_operations_quarks (); SessionObject::make_property_quarks (); diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index 491022713b..9d4e7aa836 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -2352,8 +2352,11 @@ TriggerBox::reload (BufferSet& bufs, int32_t slot, void* ptr) /* Thread */ +MultiAllocSingleReleasePool* TriggerBoxThread::Request::pool = 0; + TriggerBoxThread::TriggerBoxThread () - : _xthread (true) + : requests (1024) + , _xthread (true) { if (pthread_create_and_store ("triggerbox thread", &thread, _thread_work, this)) { error << _("Session: could not create triggerbox thread") << endmsg; @@ -2364,7 +2367,8 @@ TriggerBoxThread::TriggerBoxThread () TriggerBoxThread::~TriggerBoxThread() { void* status; - queue_request (Request::Quit); + Request* q = new Request (Quit); + queue_request (q); pthread_join (thread, &status); } @@ -2379,22 +2383,44 @@ TriggerBoxThread::_thread_work (void* arg) void * TriggerBoxThread::thread_work () { - uint32_t err = 0; - - bool disk_work_outstanding = false; - RouteList::iterator i; - 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 (); } - return (0); + return (void *) 0; } 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) { /* the x-thread channel is non-blocking * write may fail, but we really don't want to wait @@ -2410,29 +2436,20 @@ TriggerBoxThread::queue_request (Request::Type r) } } -void -TriggerBoxThread::summon () +void* +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())); - queue_request (Request::Run); + return pool->alloc (); } void -TriggerBoxThread::stop () +TriggerBoxThread::Request::operator delete (void* ptr, size_t) { - Glib::Threads::Mutex::Lock lm (request_lock); - // 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); + pool->release (ptr); } void -TriggerBoxThread::wait_until_finished () +TriggerBoxThread::Request::init_pool () { - Glib::Threads::Mutex::Lock lm (request_lock); - // 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); + pool = new MultiAllocSingleReleasePool (X_("TriggerBoxThreadRequests"), sizeof (TriggerBoxThread::Request), 1024); } - -