diff options
Diffstat (limited to 'src/worker.c')
-rw-r--r-- | src/worker.c | 113 |
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); + } +} |