Reclaim drain owns its work: invalidation only bumps a generation, and a generation that moved aborts the tick's commit and its release.

This commit is contained in:
2026-08-06 21:08:34 -04:00
parent f04c704353
commit 5dcfd3a53f
7 changed files with 321 additions and 68 deletions
+22 -6
View File
@@ -62,7 +62,9 @@ bool transportBlocksModeSwitch(ReaProject* proj) {
bool modeApplyInProgress() { return g_applying; }
bool applyMode(ViewModeModel& model, const std::string& targetModeId, ReaProject* proj) {
namespace {
bool applyModeImpl(ViewModeModel& model, const std::string& targetModeId, ReaProject* proj) {
if (g_applying) return false; // see ApplyLatch; same fail-closed shape as the guards below
ApplyLatch latch;
@@ -203,12 +205,26 @@ bool applyMode(ViewModeModel& model, const std::string& targetModeId, ReaProject
// an undo rolling the model back underneath it.
noteAppliedState(project, model);
// Every membership, snapshot and active-mode mutation in the system reaches the
// project through this call, so this is the whole invalidation surface: what the FX
// chains SHOULD be has just changed, and the reclaimer's queue is a cache of that
// intent, never state.
invalidateFxReclaim();
return true;
}
} // namespace
bool applyMode(ViewModeModel& model, const std::string& targetModeId, ReaProject* proj) {
const bool applied = applyModeImpl(model, targetModeId, proj);
// Every membership, snapshot and active-mode mutation in the system reaches the
// project through this call, so this is the whole invalidation surface: the
// reclaimer's queue is a cache of what the FX chains SHOULD be, never state.
//
// Dropped on a REFUSAL too, and that is the load-bearing half. Callers mutate the
// model FIRST and reapply to make it visible (design_view_actions' tag/untag/
// show-both, render_in_place, the load tick), and every one of them discards this
// return — so a refusal is exactly the case where the mutation stands and nothing
// else would drop a queue that now converges toward the mode the user just left.
// The cost when the refusal followed no mutation is one re-derivation on the timer.
invalidateFxReclaim();
return applied;
}
} // namespace reasampler