triggerbox: basic skeleton for an i/o and stretch thread

This commit is contained in:
Paul Davis 2021-11-09 21:47:15 -07:00
parent 7e80111d92
commit 38bf55a1fd
2 changed files with 134 additions and 1 deletions

View File

@ -19,6 +19,8 @@
#ifndef __ardour_triggerbox_h__
#define __ardour_triggerbox_h__
#include <pthread.h>
#include <atomic>
#include <map>
#include <vector>
@ -27,6 +29,7 @@
#include <glibmm/threads.h>
#include "pbd/crossthread.h"
#include "pbd/pcg_rand.h"
#include "pbd/pool.h"
#include "pbd/properties.h"
@ -330,6 +333,44 @@ class LIBARDOUR_API MIDITrigger : public Trigger {
};
class LIBARDOUR_API TriggerBoxThread
{
public:
TriggerBoxThread ();
~TriggerBoxThread();
void summon();
void stop();
void wait_until_finished();
static void* _thread_work(void *arg);
void* thread_work();
struct Request {
enum Type {
Run,
Pause,
Quit
};
};
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);
CrossThreadChannel _xthread;
};
class LIBARDOUR_API TriggerBox : public Processor
{
public:
@ -476,6 +517,11 @@ class LIBARDOUR_API TriggerBox : public Processor
void process_request (BufferSet&, Request*);
void reload (BufferSet& bufs, int32_t slot, void* ptr);
};
namespace Properties {

View File

@ -9,6 +9,7 @@
#include "pbd/basename.h"
#include "pbd/compose.h"
#include "pbd/failed_constructor.h"
#include "pbd/pthread_utils.h"
#include "pbd/types_convert.h"
#include "temporal/tempo.h"
@ -2342,10 +2343,96 @@ TriggerBox::process_request (BufferSet& bufs, Request* req)
void
TriggerBox::reload (BufferSet& bufs, int32_t slot, void* ptr)
{
if (slot >= all_triggers.size()) {
if (slot >= (int32_t) all_triggers.size()) {
return;
}
std::cerr << "reload slot " << slot << std::endl;
all_triggers[slot]->reload (bufs, ptr);
}
/* Thread */
TriggerBoxThread::TriggerBoxThread ()
: _xthread (true)
{
if (pthread_create_and_store ("triggerbox thread", &thread, _thread_work, this)) {
error << _("Session: could not create triggerbox thread") << endmsg;
throw failed_constructor ();
}
}
TriggerBoxThread::~TriggerBoxThread()
{
void* status;
queue_request (Request::Quit);
pthread_join (thread, &status);
}
void *
TriggerBoxThread::_thread_work (void* arg)
{
SessionEvent::create_per_thread_pool ("tbthread events", 4096);
pthread_set_name (X_("tbthread"));
return ((TriggerBoxThread *) arg)->thread_work ();
}
void *
TriggerBoxThread::thread_work ()
{
uint32_t err = 0;
bool disk_work_outstanding = false;
RouteList::iterator i;
while (true) {
Temporal::TempoMap::fetch ();
}
return (0);
}
void
TriggerBoxThread::queue_request (Request::Type r)
{
char c = r;
if (_xthread.deliver (c) != 1) {
/* the x-thread channel is non-blocking
* write may fail, but we really don't want to wait
* under normal circumstances.
*
* a lost "run" requests under normal RT operation
* is mostly harmless.
*
* TODO if ardour is freehweeling, wait & retry.
* ditto for Request::Type Quit
*/
assert(1); // we're screwd
}
}
void
TriggerBoxThread::summon ()
{
// DEBUG_TRACE (DEBUG::TriggerBoxThread, string_compose ("%1: summon tbthread to run @ %2\n", DEBUG_THREAD_SELF, g_get_monotonic_time()));
queue_request (Request::Run);
}
void
TriggerBoxThread::stop ()
{
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);
}
void
TriggerBoxThread::wait_until_finished ()
{
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);
}