aboutsummaryrefslogtreecommitdiffstats
path: root/src/worker.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2024-11-17 16:56:05 -0500
committerDavid Robillard <d@drobilla.net>2024-11-24 19:06:49 -0500
commitffc643c1c5f23a5c993c30bf72363dc9567aa65a (patch)
tree1ab58ff4bfae7516171e2c68f518df972ff23d2e /src/worker.c
parent73e0744d9c2381038fbda7f2c53a0aabd6780b03 (diff)
downloadjalv-ffc643c1c5f23a5c993c30bf72363dc9567aa65a.tar.gz
jalv-ffc643c1c5f23a5c993c30bf72363dc9567aa65a.tar.bz2
jalv-ffc643c1c5f23a5c993c30bf72363dc9567aa65a.zip
Clean up worker interface
Diffstat (limited to 'src/worker.c')
-rw-r--r--src/worker.c101
1 files changed, 52 insertions, 49 deletions
diff --git a/src/worker.c b/src/worker.c
index d34fedb..4592a40 100644
--- a/src/worker.c
+++ b/src/worker.c
@@ -15,17 +15,23 @@
#define MAX_PACKET_SIZE 4096U
+typedef enum {
+ STATE_SINGLE_THREADED, ///< Single-threaded worker (only state)
+ STATE_STOPPED, ///< Thread is exited
+ STATE_LAUNCHED, ///< Thread is running
+ STATE_MUST_EXIT, ///< Thread exit requested
+} WorkerState;
+
struct JalvWorkerImpl {
ZixRing* requests; ///< Requests to the worker
ZixRing* responses; ///< Responses from the worker
void* response; ///< Worker response buffer
ZixSem* lock; ///< Lock for plugin work() method
- bool exit; ///< Exit flag
ZixSem sem; ///< Worker semaphore
+ WorkerState state; ///< Worker state
ZixThread thread; ///< Worker thread
LV2_Handle handle; ///< Plugin handle
const LV2_Worker_Interface* iface; ///< Plugin worker interface
- bool threaded; ///< Run work in another thread
};
static LV2_Worker_Status
@@ -60,7 +66,7 @@ worker_func(void* const data)
while (true) {
// Wait for a request
zix_sem_wait(&worker->sem);
- if (worker->exit) {
+ if (worker->state == STATE_MUST_EXIT) {
break;
}
@@ -88,88 +94,86 @@ worker_func(void* const data)
}
free(buf);
+ worker->state = STATE_STOPPED;
return NULL;
}
-static ZixStatus
-jalv_worker_launch(JalvWorker* const worker)
-{
- ZixStatus st = ZIX_STATUS_SUCCESS;
-
- if ((st = zix_sem_init(&worker->sem, 0)) ||
- (st = zix_thread_create(&worker->thread, 4096U, worker_func, worker))) {
- return st;
- }
-
- ZixRing* const requests = zix_ring_new(NULL, MAX_PACKET_SIZE);
- if (!requests) {
- zix_thread_join(worker->thread);
- zix_sem_destroy(&worker->sem);
- return ZIX_STATUS_NO_MEM;
- }
-
- zix_ring_mlock(requests);
- worker->requests = requests;
- return ZIX_STATUS_SUCCESS;
-}
-
JalvWorker*
jalv_worker_new(ZixSem* const lock, const bool threaded)
{
JalvWorker* const worker = (JalvWorker*)calloc(1, sizeof(JalvWorker));
+ ZixRing* const requests = zix_ring_new(NULL, MAX_PACKET_SIZE);
ZixRing* const responses = zix_ring_new(NULL, MAX_PACKET_SIZE);
void* const response = calloc(1, MAX_PACKET_SIZE);
if (worker && responses && response) {
- worker->threaded = threaded;
+ worker->requests = requests;
worker->responses = responses;
worker->response = response;
worker->lock = lock;
- worker->exit = false;
+ worker->state = threaded ? STATE_STOPPED : STATE_SINGLE_THREADED;
+ zix_ring_mlock(requests);
zix_ring_mlock(responses);
- if (!threaded || !jalv_worker_launch(worker)) {
- return worker;
- }
+ return worker;
}
free(response);
zix_ring_free(responses);
+ zix_ring_free(requests);
free(worker);
return NULL;
}
void
-jalv_worker_attach(JalvWorker* const worker,
- const LV2_Worker_Interface* const iface,
- LV2_Handle handle)
+jalv_worker_free(JalvWorker* const worker)
{
if (worker) {
- worker->iface = iface;
- worker->handle = handle;
+ jalv_worker_exit(worker);
+ zix_ring_free(worker->requests);
+ zix_ring_free(worker->responses);
+ free(worker->response);
+ free(worker);
+ }
+}
+
+ZixStatus
+jalv_worker_launch(JalvWorker* const worker)
+{
+ ZixStatus st = ZIX_STATUS_SUCCESS;
+ if (worker->state == STATE_STOPPED) {
+ if ((st = zix_sem_init(&worker->sem, 0))) {
+ return st;
+ }
+
+ if ((st = zix_thread_create(&worker->thread, 4096U, worker_func, worker))) {
+ zix_sem_destroy(&worker->sem);
+ return st;
+ }
+
+ worker->state = STATE_LAUNCHED;
}
+ return ZIX_STATUS_SUCCESS;
}
void
jalv_worker_exit(JalvWorker* const worker)
{
- if (worker && worker->threaded) {
- worker->exit = true;
+ if (worker && worker->state == STATE_LAUNCHED) {
+ worker->state = STATE_MUST_EXIT;
zix_sem_post(&worker->sem);
zix_thread_join(worker->thread);
- worker->threaded = false;
}
}
void
-jalv_worker_free(JalvWorker* const worker)
+jalv_worker_attach(JalvWorker* const worker,
+ const LV2_Worker_Interface* const iface,
+ LV2_Handle handle)
{
if (worker) {
- jalv_worker_exit(worker);
- zix_ring_free(worker->requests);
- zix_ring_free(worker->responses);
- free(worker->response);
- free(worker);
+ worker->iface = iface;
+ worker->handle = handle;
}
}
@@ -181,17 +185,16 @@ jalv_worker_schedule(LV2_Worker_Schedule_Handle handle,
JalvWorker* const worker = (JalvWorker*)handle;
LV2_Worker_Status st = LV2_WORKER_SUCCESS;
- if (!worker || !size) {
- return LV2_WORKER_ERR_UNKNOWN;
- }
+ if (!worker || !size || worker->state == STATE_STOPPED) {
+ st = LV2_WORKER_ERR_UNKNOWN;
- if (worker->threaded) {
+ } else if (worker->state == STATE_LAUNCHED) {
// Schedule a request to be executed by the worker thread
if (!(st = jalv_worker_write_packet(worker->requests, size, data))) {
zix_sem_post(&worker->sem);
}
- } else {
+ } else if (worker->state == STATE_SINGLE_THREADED) {
// Execute work immediately in this thread
zix_sem_wait(worker->lock);
st = worker->iface->work(