Repository navigation
HttpFrameGrabber: read a frame with its own count (TryAcquireLatest(out int)); frame and count change together - #4
Conversation
…test(out int frameCount) reads both in one locked read FrameCount was incremented after the frame swap, outside the frame lock, so no reader could pair a frame with its own count: a new frame could be read under the previous count and again under its own (rocket-welder2 #441 review S-11). Existing members unchanged. Deterministic test: the publish is held right after the swap while a reader reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mjpeg PR 4: a frame and its count in one locked read (PR 444 S-11)Verdict: APPROVE at 05a78c7, with one Should:
Is every writer of
Can a reader see its handle disposed by the publisher? No. The lifetime is unchanged.
Is the lock held across anything slow? No.
The interleaving test is deterministic.
The test seam.
Public API: nothing breaks.
Versioning.
Conventions: met. No id, event or wire type, and one private int field under the existing lock ( ShouldS-14. The shared camera feed keeps S-11's race after this PR.
|
… frame with its own count (review S-14) The shared feed read FrameCount and TryAcquireLatest() separately, so the race stayed for its consumers (rocket-welder2's CameraDevice). Existing members unchanged; the new overloads go through HttpFrameGrabber.TryAcquireLatest(out int). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mjpeg PR 4 re-read at 2980e37 (S-14)Verdict: APPROVE at 2980e37. S-14 is closed on the mjpeg side.
The paired reads on
What rw2 must change after the bump to
|
|
Merged on an approved review and a side-by-side run of the CI workflow's own steps on tycho (2026-11-13): master For the repo's owner, not done here: the workflow should either filter out 🤖 Generated with Claude Code |
HttpFrameGrabbercould not give a frame together with its own count.PublishFrameswapped_latestunder_frameLockbut incremented_frameCountafter the lock. So no read order from outside could pair them: a new frame could be read under the previous count, and then again under its own. One frame then looks like two to a consumer that tells frames apart by count. Found in rocket-welder2 PR 444 review (S-11): rw2's settle gate uses the count to tell frames apart (rw2 #441).Change
PublishFramestores the frame and its count together, inside the lock (_latestCount = Interlocked.Increment(ref _frameCount)next to_latest = handle).JpegFrameHandle? TryAcquireLatest(out int frameCount)returns the handle and the count it was published under, from one locked read.TryAcquireLatest()now delegates to it.FrameCount,HasFrameandTryAcquireLatest(), in signature and meaning.FrameCount's doc now says that, read on its own, it does not identify the frameTryAcquireLatest()returns.PublishFramebecomesinternal, plus aninternalhookAfterSwapForTestandInternalsVisibleTothe test project.Consumers checked
In rocket-welder2,
LiveRawFrameSourceis the only reader ofFrameCount/TryAcquireLatest.CameraStreamServicementions the grabber in a comment and readsCameraDevice.FrameCount, a different counter. No other repository in the workspace index usesHttpFrameGrabber(checked: rocket-welder-sdk, streamer, native-player, platform).Moving the increment inside the lock changes nothing visible to them:
FrameCountis still a volatile read of the same counter._hasFrameis still set after the publish.Tests
HttpFrameGrabberFrameCountTests(new, no network):Category=Integrationtests (HttpFrameGrabberTests,MjpegProviderTests) need a live MJPEG stream on 127.0.0.1:4953. Here they fail with connection refused, as they would on master with no stream.Review S-14 (head 2980e37)
MjpegProvider, the shared feed rocket-welder2'sCameraDeviceis built on, gainsTryGetFrame(out int frameCount)andTryAcquireRaw(out int frameCount). Both go throughHttpFrameGrabber.TryAcquireLatest(out int). The existingTryGetFrame(),TryAcquireRaw()andFrameCountare unchanged.FrameCount, then the frame, over today's grabber): the provider interleaving test fails, as does the grabber's.Release
None in this PR. Publishing a new version needs the owner's word. rocket-welder2 then bumps 1.4.1 to the new version (which also brings 1.5.0's Rgb24 codec) and moves
LiveRawFrameSourcetoTryAcquireLatest(out int).🤖 Generated with Claude Code