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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user