fix: a recompute that renumbered its ring, and readouts frozen under a zoom
Three defects, all of them a window describing data that is not there. A math edit refilled the derived ring with `clear()`, which renumbers it from 0, leaving `produced()` short by the inputs' retained base. Since `live_window_locked()` clamps against every channel's `produced()`, that one lagging channel answered `n = 0` for the live view, every pause view and every trigger capture until a whole ring of fresh data had gone by -- the reported freeze, invisible until the ring first wraps, hence its intermittence. It now restarts with `clear_to(base)`, and `ChannelBuffer::republish_from(base)` puts the published window back: `acquire()` is incremental, so a rewrite in place published nothing and the pyramid went on describing the samples the edit replaced. The trigger's channel is an index, re-resolved by name after a renumbering -- but only in `rebuild_enabled_locked()`, so a math add or delete went through `set_math_channels()` with no restore, the index was clamped to -1, and `process()` returned at once while the panel still named the channel. The restore moves into `rebuild_channels()`, which *is* the renumbering, so no caller can forget it. And `update_measures()` suppressed its "the window moved" test while an event was held -- the one mode where a gesture is the only thing that can move it. Zooming a latched event left the pane describing the whole captured event. A pinned window needs no exemption: it lands on the range it already measured and fails the 2 % test by itself. The checks that missed all three: `UDPSCOPE_PROBE_MATHWRAP_MS` edits a graph whose ring has already wrapped, which `math_probe` structurally cannot reach; `[measure-trace]` now prints the mode, the window on screen and the window the numbers describe; and the dump's `marks_in_window` counts against the window on screen instead of against the one the marks were computed over, where it was a tautology. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
074cb611bc
commit
d91957a2fe
15 files changed
+374
-45
No files matched your search
@@ -323,6 +323,28 @@ the assertion: `finite` must be about `M` minus the hole share, and `finite=0` b
|
||||
`[math-probe] graph edit: stored_slots N -> M` reads it: M must be at least N -- the store keeps filling
|
||||
while the edit runs -- and never 0.
|
||||
|
||||
- **A recompute rewrites a ring *in place*, and both of the ring's counters have to survive it.**
|
||||
`recompute_math_locked()` replays the inputs' **retained** window, which begins at the time ring's
|
||||
`base()` and not at zero, so an emptied derived ring is restarted with `clear_to(base)` and never
|
||||
`clear()`. With `clear()` the refill renumbered the channel from 0 and left its `produced()` short by
|
||||
exactly `base` -- and `live_window_locked()` clamps its window against *every* channel's `produced()`,
|
||||
so that one lagging channel answered `n = 0` for the live view, every pause view **and** every trigger
|
||||
capture, until a whole ring of fresh data had gone by. That is the "a math edit freezes acquisition,
|
||||
and the trigger stops firing on a channel that is not even derived" report, and it is **invisible
|
||||
before the ring first wraps** (`base == 0`, where the two numberings coincide), which is why it reads
|
||||
as intermittent and uptime-dependent. The dump's `math '<name>': N samples vs M time slots` is the
|
||||
reading -- both numbers are `produced()`, so a mismatch *is* this defect -- but only on a run whose
|
||||
ring has wrapped: give it a small `--buffer-mb`. `UDPSCOPE_PROBE_MATHWRAP_MS` is the probe that
|
||||
arranges exactly that, and it exists because **`math_probe` structurally cannot** reach this state:
|
||||
every edit that probe makes follows a structural change, which replans the buffer and restarts every
|
||||
ring at absolute 0, where both halves of this are identities.
|
||||
The published window is the second counter. `acquire()` is incremental, so a rewrite that leaves
|
||||
`produced()` where it was publishes **nothing** and the pyramid -- what the renderer and every
|
||||
measurement read -- goes on describing the samples the edit replaced. `ChannelBuffer::republish_from(base)`
|
||||
is what puts it back, and it takes the ring's base rather than 0 because `invalidate()` would make the
|
||||
next `acquire()` walk every absolute index ever produced (an hour at 1 MS/s is 3.6 G appends) to publish
|
||||
one window.
|
||||
|
||||
- **A math channel whose source is switched off is switched off with it.** `Source` resolves to a *channel*, so
|
||||
a derived channel cannot be computed from a signal nobody acquires: left enabled it would silently compute
|
||||
nothing, which is what "all math signals depending on it do not compute anymore" looked like from outside.
|
||||
|
||||
Reference in new issue
Block a user