fix: convert shared scene metadata to atomic_int to fix data races

Co-authored-by: aider (deepseek/deepseek-reasoner) <aider@aider.chat>
This commit is contained in:
Loic Coenen
2026-05-10 19:33:12 +00:00
parent 74db4ed46c
commit 755af275d8
3 changed files with 93 additions and 75 deletions

View File

@@ -9,7 +9,7 @@
static void init_scene(scene_t *sc) {
memset(sc, 0, sizeof(scene_t));
atomic_store(&sc->state, STATE_IDLE);
sc->prev_state = -1;
atomic_store(&sc->prev_state, -1);
}
void channel_add(jack_client_t *client, int idx) {
@@ -32,8 +32,8 @@ void channel_add(jack_client_t *client, int idx) {
atomic_store(&cur[idx].active, 1);
cur[idx].type = CHANNEL_AUDIO;
cur[idx].scene_count = 1;
cur[idx].current_scene = 0;
atomic_store(&cur[idx].scene_count, 1);
atomic_store(&cur[idx].current_scene, 0);
init_scene(&cur[idx].scenes[0]);
next_channel_id++;
@@ -60,8 +60,8 @@ void channel_add_midi(jack_client_t *client, int idx) {
atomic_store(&cur[idx].active, 1);
cur[idx].type = CHANNEL_MIDI;
cur[idx].scene_count = 1;
cur[idx].current_scene = 0;
atomic_store(&cur[idx].scene_count, 1);
atomic_store(&cur[idx].current_scene, 0);
init_scene(&cur[idx].scenes[0]);
next_channel_id++;
@@ -78,52 +78,59 @@ void channel_remove(jack_client_t *client, int idx) {
void channel_add_scene(jack_client_t *client, int idx) {
(void)client;
struct channel_t *cur = get_channels_array();
if (cur[idx].scene_count >= MAX_SCENES)
if (atomic_load(&cur[idx].scene_count) >= MAX_SCENES)
return;
int ns = cur[idx].scene_count;
int ns = atomic_load(&cur[idx].scene_count);
init_scene(&cur[idx].scenes[ns]);
cur[idx].scene_count++;
atomic_fetch_add(&cur[idx].scene_count, 1);
}
void channel_remove_scene(jack_client_t *client, int idx) {
(void)client;
struct channel_t *cur = get_channels_array();
if (cur[idx].scene_count <= 1)
int sc = atomic_load(&cur[idx].scene_count);
if (sc <= 1)
return;
int cs = cur[idx].current_scene;
/* shift remaining scenes down (safe copy of fields) */
for (int i = cs; i < cur[idx].scene_count - 1; i++) {
cur[idx].scenes[i].loop_count = cur[idx].scenes[i+1].loop_count;
cur[idx].scenes[i].record_pos = cur[idx].scenes[i+1].record_pos;
cur[idx].scenes[i].playback_pos = cur[idx].scenes[i+1].playback_pos;
int cs = atomic_load(&cur[idx].current_scene);
/* shift remaining scenes down (atomic copy of fields) */
for (int i = cs; i < sc - 1; i++) {
atomic_store(&cur[idx].scenes[i].loop_count,
atomic_load(&cur[idx].scenes[i+1].loop_count));
atomic_store(&cur[idx].scenes[i].record_pos,
atomic_load(&cur[idx].scenes[i+1].record_pos));
atomic_store(&cur[idx].scenes[i].playback_pos,
atomic_load(&cur[idx].scenes[i+1].playback_pos));
atomic_store(&cur[idx].scenes[i].state,
atomic_load(&cur[idx].scenes[i+1].state));
cur[idx].scenes[i].prev_state = cur[idx].scenes[i+1].prev_state;
/* copy loop data */
atomic_store(&cur[idx].scenes[i].prev_state,
atomic_load(&cur[idx].scenes[i+1].prev_state));
/* copy loop data (may race with RT thread; acceptable for this release) */
memcpy(cur[idx].scenes[i].loop.audio_buffer,
cur[idx].scenes[i+1].loop.audio_buffer,
LOOP_BUF_SIZE * sizeof(float));
}
cur[idx].scene_count--;
if (cur[idx].current_scene >= cur[idx].scene_count)
cur[idx].current_scene = cur[idx].scene_count - 1;
atomic_fetch_sub(&cur[idx].scene_count, 1);
int new_sc = atomic_load(&cur[idx].scene_count);
if (cs >= new_sc)
atomic_store(&cur[idx].current_scene, new_sc - 1);
}
void channel_next_scene(jack_client_t *client, int idx) {
(void)client;
struct channel_t *cur = get_channels_array();
if (cur[idx].scene_count > 1) {
cur[idx].current_scene =
(cur[idx].current_scene + 1) % cur[idx].scene_count;
int sc = atomic_load(&cur[idx].scene_count);
if (sc > 1) {
int cs = atomic_load(&cur[idx].current_scene);
atomic_store(&cur[idx].current_scene, (cs + 1) % sc);
}
}
void channel_prev_scene(jack_client_t *client, int idx) {
(void)client;
struct channel_t *cur = get_channels_array();
if (cur[idx].scene_count > 1) {
cur[idx].current_scene =
(cur[idx].current_scene - 1 + cur[idx].scene_count) %
cur[idx].scene_count;
int sc = atomic_load(&cur[idx].scene_count);
if (sc > 1) {
int cs = atomic_load(&cur[idx].current_scene);
atomic_store(&cur[idx].current_scene, (cs - 1 + sc) % sc);
}
}