Narrow the FX reclaimer's transport gate to defer offline work only; let online drain through, and always run the park clock's observe
This commit is contained in:
@@ -110,8 +110,8 @@ struct ReclaimHost {
|
||||
}
|
||||
|
||||
// The SAME predicate applyMode refuses a real mode switch on, deliberately shared
|
||||
// rather than re-read here: what counts as a transport that must not have plugins
|
||||
// moved under it is one fact with one home (view.h).
|
||||
// rather than re-read here: "the transport is rolling" is one fact with one home
|
||||
// (view.h). drainTick narrows what it gates with this answer to offline work only.
|
||||
bool transportRolling() const { return transportBlocksModeSwitch(project); }
|
||||
|
||||
bool liveChain(const std::string& guid, std::vector<std::string>& out) {
|
||||
|
||||
+26
-15
@@ -173,8 +173,9 @@ struct ReclaimTickResult {
|
||||
// fx_reclaim.cpp holds the one live implementation. Host must provide:
|
||||
//
|
||||
// double nowMs() monotonic milliseconds
|
||||
// bool transportRolling() playing or recording — the tick
|
||||
// may move no plugins at all
|
||||
// bool transportRolling() playing or recording — gates the
|
||||
// OFFLINE direction only; a tick
|
||||
// may still online while it rolls
|
||||
// bool liveChain(guid, std::vector<std::string>&) FX identity per live slot;
|
||||
// false when the track is gone
|
||||
// bool writeOffline(guid, fxIndex, offline) compare-before-write inside its
|
||||
@@ -194,20 +195,30 @@ template <class Host>
|
||||
ReclaimTickResult drainTick(std::vector<ReclaimItem>& items, ParkClock& clock, Host& host) {
|
||||
ReclaimTickResult result;
|
||||
|
||||
// Mirrors applyMode's refusal (view.h, transportBlocksModeSwitch), and now covers
|
||||
// every FX write the tool makes, since this loop owns them all. BOTH directions, not
|
||||
// just the opportunistic offline one: onlining re-instantiates the very plugins the
|
||||
// user is listening through — the same destruction the switch already refuses — and a
|
||||
// step is a whole chain with no yield inside it. Nothing is observed on this path, so
|
||||
// every debounce hold keeps its origin and the first ungated tick fires with no wait.
|
||||
if (host.transportRolling()) {
|
||||
result.settled = queueSettled(items);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Run every tick, rolling or not: matured()'s own contract ("observe() runs first
|
||||
// every tick") already assumed this, and a track can stop owing offline work on a
|
||||
// rolling tick too now that this loop keeps writing online through one — a
|
||||
// continuously-parked track's origin is untouched (observe carries the prior
|
||||
// timestamp forward), so the only thing this changes is dropping a hold the moment
|
||||
// its track genuinely stops owing offline work, matured or not.
|
||||
clock.observe(items, host.nowMs());
|
||||
|
||||
const int first = nextEligible(items, clock, host.nowMs());
|
||||
// Mirrors applyMode's refusal (view.h, transportBlocksModeSwitch), narrowed to the
|
||||
// OFFLINE direction only: onlining is the mode switch's own unfinished promise — the
|
||||
// user is waiting on it — while offlining is opportunistic reclaim that can always
|
||||
// wait for the transport to stop. Onlining while rolling still costs a plugin load
|
||||
// mid-playback; that is an accepted trade for this gate's shape, not a hazard it
|
||||
// introduces.
|
||||
const bool offlineAllowed = !host.transportRolling();
|
||||
auto nextAllowed = [&](double nowMs) {
|
||||
const int i = nextEligible(items, clock, nowMs);
|
||||
if (i >= 0 && !offlineAllowed &&
|
||||
items[static_cast<std::size_t>(i)].work.kind == view::FxWorkKind::Offline)
|
||||
return -1;
|
||||
return i;
|
||||
};
|
||||
|
||||
const int first = nextAllowed(host.nowMs());
|
||||
if (first < 0) {
|
||||
result.settled = queueSettled(items);
|
||||
return result;
|
||||
@@ -218,7 +229,7 @@ ReclaimTickResult drainTick(std::vector<ReclaimItem>& items, ParkClock& clock, H
|
||||
const double start = host.nowMs();
|
||||
|
||||
for (;;) {
|
||||
const int i = nextEligible(items, clock, host.nowMs());
|
||||
const int i = nextAllowed(host.nowMs());
|
||||
if (i < 0) break;
|
||||
ReclaimItem& item = items[static_cast<std::size_t>(i)];
|
||||
// Offline work never rides the online budget: the two directions are priced
|
||||
|
||||
Reference in New Issue
Block a user