aboutsummaryrefslogtreecommitdiffstats
path: root/src/worker.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-08-10 17:11:13 -0400
committerDavid Robillard <d@drobilla.net>2022-08-17 13:51:11 -0400
commit5cdf800837b2e8062042b300b1755db2482a89e3 (patch)
tree4cbfd92143d26db800892a495b30e461d7dea0aa /src/worker.c
parent19c9e4a59b92ce1aaf2ae0cefe2e0f2b6e2e44e3 (diff)
downloadjalv-5cdf800837b2e8062042b300b1755db2482a89e3.tar.gz
jalv-5cdf800837b2e8062042b300b1755db2482a89e3.tar.bz2
jalv-5cdf800837b2e8062042b300b1755db2482a89e3.zip
Make worker opaque
Diffstat (limited to 'src/worker.c')
-rw-r--r--src/worker.c113
1 files changed, 90 insertions, 23 deletions
diff --git a/src/worker.c b/src/worker.c
index 1fdfaaf..63df419 100644
--- a/src/worker.c
+++ b/src/worker.c
@@ -5,6 +5,7 @@
#include "lv2/core/lv2.h"
#include "lv2/worker/worker.h"
+#include "zix/common.h"
#include "zix/ring.h"
#include "zix/sem.h"
#include "zix/thread.h"
@@ -14,6 +15,19 @@
#define MAX_PACKET_SIZE 4096U
+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
+ 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
jalv_worker_write_packet(ZixRing* const target,
const uint32_t size,
@@ -46,7 +60,7 @@ worker_func(void* const data)
while (true) {
// Wait for a request
zix_sem_wait(&worker->sem);
- if (*worker->exit) {
+ if (worker->exit) {
break;
}
@@ -77,41 +91,86 @@ worker_func(void* const data)
return NULL;
}
-void
-jalv_worker_init(JalvWorker* const worker,
- const LV2_Worker_Interface* const iface,
- const bool threaded)
+static ZixStatus
+jalv_worker_launch(JalvWorker* const worker)
{
- worker->iface = iface;
- worker->threaded = threaded;
- worker->responses = zix_ring_new(NULL, MAX_PACKET_SIZE);
- worker->response = malloc(MAX_PACKET_SIZE);
+ 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, NULL);
+ zix_sem_destroy(&worker->sem);
+ return ZIX_STATUS_NO_MEM;
+ }
- if (threaded) {
- worker->requests = zix_ring_new(NULL, MAX_PACKET_SIZE);
+ zix_ring_mlock(requests);
+ worker->requests = requests;
+ return ZIX_STATUS_SUCCESS;
+}
- zix_thread_create(&worker->thread, 4096U, worker_func, worker);
- zix_ring_mlock(worker->requests);
+JalvWorker*
+jalv_worker_new(ZixSem* const lock, const bool threaded)
+{
+ JalvWorker* const worker = (JalvWorker*)calloc(1, sizeof(JalvWorker));
+ 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->responses = responses;
+ worker->response = response;
+ worker->lock = lock;
+ worker->exit = false;
+
+ zix_ring_mlock(responses);
+ if (!threaded || !jalv_worker_launch(worker)) {
+ return worker;
+ }
}
- zix_ring_mlock(worker->responses);
+ free(worker);
+ zix_ring_free(responses);
+ free(response);
+ return NULL;
}
void
-jalv_worker_finish(JalvWorker* const worker)
+jalv_worker_start(JalvWorker* const worker,
+ const LV2_Worker_Interface* const iface,
+ LV2_Handle handle)
{
- if (worker->threaded) {
+ if (worker) {
+ worker->iface = iface;
+ worker->handle = handle;
+ }
+}
+
+void
+jalv_worker_exit(JalvWorker* const worker)
+{
+ if (worker && worker->threaded) {
+ worker->exit = true;
zix_sem_post(&worker->sem);
zix_thread_join(worker->thread, NULL);
+ worker->threaded = false;
}
}
void
-jalv_worker_destroy(JalvWorker* const worker)
+jalv_worker_free(JalvWorker* const worker)
{
- zix_ring_free(worker->requests);
- zix_ring_free(worker->responses);
- free(worker->response);
+ if (worker) {
+ jalv_worker_exit(worker);
+ zix_ring_free(worker->requests);
+ zix_ring_free(worker->responses);
+ free(worker->response);
+ free(worker);
+ }
}
LV2_Worker_Status
@@ -119,10 +178,10 @@ jalv_worker_schedule(LV2_Worker_Schedule_Handle handle,
const uint32_t size,
const void* const data)
{
- JalvWorker* worker = (JalvWorker*)handle;
+ JalvWorker* const worker = (JalvWorker*)handle;
LV2_Worker_Status st = LV2_WORKER_SUCCESS;
- if (!size) {
+ if (!worker || !size) {
return LV2_WORKER_ERR_UNKNOWN;
}
@@ -148,7 +207,7 @@ jalv_worker_emit_responses(JalvWorker* const worker, LV2_Handle lv2_handle)
{
static const uint32_t size_size = (uint32_t)sizeof(uint32_t);
- if (worker->responses) {
+ if (worker && worker->responses) {
uint32_t size = 0U;
while (zix_ring_read(worker->responses, &size, size_size) == size_size) {
if (zix_ring_read(worker->responses, worker->response, size) == size) {
@@ -157,3 +216,11 @@ jalv_worker_emit_responses(JalvWorker* const worker, LV2_Handle lv2_handle)
}
}
}
+
+void
+jalv_worker_end_run(JalvWorker* const worker)
+{
+ if (worker && worker->iface && worker->iface->end_run) {
+ worker->iface->end_run(worker->handle);
+ }
+}