Phase 10: Audit engine reliability and strengthen lifecycle regression tests

This commit is contained in:
Johannes Findeisen 2026-10-27 03:17:29 +01:00
commit 8dd96d3cc5
13 changed files with 394 additions and 5 deletions

View file

@ -1,11 +1,46 @@
#define _POSIX_C_SOURCE 200809L
#include "xtc/xtc_realtime.h"
#include "xtc/xtc_native.h"
#include <assert.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#define CHECK(c) do { if (!(c)) { fprintf(stderr,"FAIL %s:%d: %s\n",__FILE__,__LINE__,#c); return 1; } } while (0)
/* Count native lifetimes on the serialized producer while a real consumer
* traverses plans. Destruction on that consumer is always a contract violation. */
static pthread_t control_thread;
static unsigned int prepared, destroyed;
static xtc_result prepare(double rate, size_t frames, float gain, void **state)
{
(void)rate; (void)frames;
assert(pthread_equal(pthread_self(), control_thread));
*state = malloc(sizeof(float));
if (!*state) return XTC_ERR_OUT_OF_MEMORY;
*(float *)*state = gain;
++prepared;
return XTC_OK;
}
static void reset(void *state) { (void)state; }
static xtc_result process(void *state, const xtc_native_block *block)
{
size_t i;
for (i = 0; i < block->frames; ++i)
block->output[i] = block->input[i] * *(float *)state;
return XTC_OK;
}
static void destroy(void *state)
{
assert(pthread_equal(pthread_self(), control_thread));
if (state) ++destroyed;
free(state);
}
static const xtc_native_descriptor descriptor = {
XTC_NATIVE_ABI_VERSION, sizeof(xtc_native_descriptor), "concurrent.gain",
XTC_NATIVE_EFFECT, prepare, reset, process, destroy
};
typedef struct { xtc_realtime *engine; unsigned int stop, failed; } worker_state;
static void *worker(void *context)
{
@ -40,9 +75,9 @@ static int run(void)
CHECK(xtc_realtime_create(48000.0, 32U, &engine) == XTC_OK);
CHECK(xtc_realtime_process(engine, input, output, 4U) == XTC_OK && output[0] == 0.0f);
CHECK(xtc_graph_create(1U, &one) == XTC_OK);
CHECK(xtc_graph_add_gain(one, 1.0f, &node) == XTC_OK);
CHECK(xtc_graph_add_native(one, &descriptor, 1.0f, &node) == XTC_OK);
CHECK(xtc_graph_create(1U, &two) == XTC_OK);
CHECK(xtc_graph_add_gain(two, 2.0f, &node) == XTC_OK);
CHECK(xtc_graph_add_native(two, &descriptor, 2.0f, &node) == XTC_OK);
CHECK(xtc_realtime_submit(engine, one) == XTC_OK);
CHECK(xtc_realtime_submit(engine, two) == XTC_ERR_CAPACITY);
CHECK(xtc_realtime_get_status(engine, &status) == XTC_OK && status.submitted_revision == 1U && status.active_revision == 0U);
@ -68,6 +103,7 @@ static int run(void)
CHECK(state.failed == 0U);
CHECK(xtc_realtime_get_status(engine, &status) == XTC_OK && status.processed_blocks > 3U);
xtc_realtime_destroy(engine); /* Also cleans pending and retired plans. */
CHECK(prepared == destroyed);
xtc_graph_destroy(one); xtc_graph_destroy(two);
for (i = 0U; i < 100U; ++i) {
CHECK(xtc_realtime_create(48000.0, 4U, &engine) == XTC_OK);
@ -80,6 +116,7 @@ static int run(void)
}
int main(void)
{
control_thread = pthread_self();
CHECK(run() == 0);
puts("Realtime handoff and concurrent replacement tests passed.");
return 0;