ModuLisp/src/signal_engine/state_registry.cpp

114 lines
3.9 KiB
C++
Raw Normal View History

#include "state_registry.h"
#include <cstring>
namespace sig {
uint16_t StateResourceRegistry::resolve(const StateResourceKey& key,
Sample init_value,
Sample* state_values,
uint16_t& state_slot_count,
uint16_t owner_context) {
last_owner_conflict = false;
// Search for existing entry
for (uint16_t i = 0; i < entry_count; i++) {
if (entries[i].key == key) {
if (owner_context != ANON_STATE_CONTEXT_NONE &&
entries[i].owner_context != ANON_STATE_CONTEXT_NONE &&
entries[i].owner_context != owner_context) {
last_owner_conflict = true;
return NODE_NONE;
}
if (entries[i].owner_context == ANON_STATE_CONTEXT_NONE) {
entries[i].owner_context = owner_context;
}
entries[i].active = true;
return entries[i].slot_index;
}
}
// New entry — prefer a slot retired by a previously published graph.
if (entry_count >= MAX_STATE_SLOTS) return NODE_NONE;
uint16_t slot = take_free_slot();
if (slot == NODE_NONE) {
if (state_slot_count >= MAX_STATE_SLOTS) return NODE_NONE;
slot = state_slot_count++;
}
state_values[slot] = init_value;
entries[entry_count].key = key;
entries[entry_count].slot_index = slot;
entries[entry_count].owner_context = owner_context;
entries[entry_count].init_value = init_value;
entries[entry_count].active = true;
entry_count++;
return slot;
}
void StateResourceRegistry::begin_context(uint16_t owner_context) {
if (owner_context == ANON_STATE_CONTEXT_NONE) return;
for (uint16_t i = 0; i < entry_count; i++) {
if (entries[i].owner_context == owner_context) {
entries[i].active = false;
}
}
}
void StateResourceRegistry::commit_context(
uint16_t owner_context, uint16_t* state_update_roots,
uint16_t* state_owner_contexts) {
if (owner_context == ANON_STATE_CONTEXT_NONE) return;
uint16_t write = 0;
for (uint16_t read = 0; read < entry_count; read++) {
StateResourceEntry& entry = entries[read];
if (entry.owner_context == owner_context && !entry.active) {
if (entry.slot_index < MAX_STATE_SLOTS) {
state_update_roots[entry.slot_index] = NODE_NONE;
state_owner_contexts[entry.slot_index] =
ANON_STATE_CONTEXT_NONE;
// Each live registry entry owns a unique slot. Avoid adding a
// duplicate defensively so a malformed legacy image cannot
// make the same slot available twice.
bool already_free = false;
for (uint16_t f = 0; f < free_slot_count; f++) {
if (free_slots[f] == entry.slot_index) {
already_free = true;
break;
}
}
if (!already_free && free_slot_count < MAX_STATE_SLOTS) {
free_slots[free_slot_count++] = entry.slot_index;
}
}
continue;
}
if (write != read) entries[write] = entries[read];
write++;
}
entry_count = write;
}
uint16_t StateResourceRegistry::take_free_slot() {
if (free_slot_count == 0) return NODE_NONE;
return free_slots[--free_slot_count];
}
void StateResourceRegistry::mark_all_inactive() {
for (uint16_t i = 0; i < entry_count; i++) {
entries[i].active = false;
}
}
void StateResourceRegistry::clear() {
for (uint16_t i = 0; i < MAX_STATE_SLOTS; i++) {
entries[i] = StateResourceEntry{};
free_slots[i] = NODE_NONE;
}
entry_count = 0;
free_slot_count = 0;
last_owner_conflict = false;
}
} // namespace sig