spinPoll method
Busy-polls the armed slot (issue #57), capped at capUs µs. Returns a
one-element [raw] when the completion lands off-port — no port message,
no OS wake — or null when it parks, leaving the normal port callback to
deliver it. Single-in-flight only.
The loop breaks the instant the completion lands, so capUs is an upper
bound, not a fixed spend: a hit only ever spins until its result arrives,
however large the cap. The cap therefore bounds just the miss path, and
a circuit breaker caps even that — after a run of misses (the native side
is reliably slower than capUs, so spinning can't win) the window drops
to zero and calls park immediately, probing at the full cap every
_probeEvery calls. NitroSpinStats reports the hit-rate so you can see
whether the cap is set usefully.
Implementation
List<dynamic>? spinPoll(int id, int capUs) {
final window = _effectiveWindow(capUs);
final out = _spinOut ??= () {
final buf = calloc<Uint8>(24);
_spinOutFinalizer.attach(this, buf.cast(), detach: this, externalSize: 24);
return buf;
}();
var state = 0; // 0 pending, 1 done, 2 parked
final sw = Stopwatch()..start();
if (window > 0) {
// Poll in bursts between clock reads (a clock read ~150 ns dwarfs a leaf
// poll ~few ns), so the loop stays poll-bound and catches a completion
// within ns of it landing rather than within a clock-read.
outer:
while (sw.elapsedMicroseconds < window) {
for (var k = 0; k < 64; k++) {
state = poll(id, out, 0);
if (state != 0) break outer;
}
}
}
if (state == 0) state = poll(id, out, 1); // deadline: claim-or-park
_dutySpentUs += sw.elapsedMicroseconds; // charge actual busy-wait to the budget
if (state != 1) {
// Parked → the port path takes over.
_countMiss();
NitroSpinStats.instance.recordMiss();
// Measure this miss's true latency when its port message lands — but only
// if we actually spun (a breaker-forced window==0 park never armed a fresh
// clock and isn't a real "the cap was too tight" miss).
if (window > 0) _awaitingParkLatency = true;
return null;
}
// Hit: delivered off-port; the port callback must not fire.
final hitUs = sw.elapsedMicroseconds;
// An edge hit (spun almost the whole window before landing) paid nearly the
// full miss cost; the miss-only breaker can't see it, so a worker that lands
// at the boundary every call would spin near-full-window forever. Count it
// toward backoff; only a comfortably-early hit (the common ~µs case) resumes.
if (window > 0 && hitUs > window - (window >> 3)) {
_countMiss();
} else {
_recentMisses = 0;
_backedOff = false;
}
NitroSpinStats.instance.recordHit(hitUs);
_pending.remove(id);
return [_decodeSlot(out)];
}