Repository navigation
Read and replace the request under one lock in SetKeepDisplayAwake [minor] - #42
Merged
Merged
Conversation
…inor] SetKeepDisplayAwake read Request under the controller's lock, released it, then took it again in SetRequest to write a modified copy. A concurrent request change landing in between was overwritten while StateChanged still reported both. Add SetRequest(Func<SleepBlockRequest, SleepBlockRequest>), which computes the new request from the current one inside the lock, and route SetKeepDisplayAwake, SetRequest(request) and the tool's --reason option through it. Fixes #39 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017vfJW4SLyvTvUJUdcrUu7F
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes #39
What changed
SetKeepDisplayAwakereadRequestundergate, released the lock, and then took it again inSetRequestto write a modified copy. If another request change landed in that gap, it was overwritten, andStateChangedstill fired for both calls. This is the request-path counterpart of #30. The fix has the same shape as #31: the decision is made inside the lock.SetRequest(Func<SleepBlockRequest, SleepBlockRequest> update). It runsupdateon the request in force undergate, then applies the result. Behaviour is otherwise unchanged: re-acquire when active, no event when nothing changed. Anullresult throwsArgumentNullExceptionand leaves the request alone. Because the overload is public, it's a[minor]change. Callers get atomic partial edits such asSetRequest(current => current with { Reason = "Rendering" }).SetKeepDisplayAwakeandSetRequest(SleepBlockRequest)now both go through it.--reasonoption used the same racySetRequest(controller.Request with { … })shape. It now uses the overload.Tests
SetKeepDisplayAwake_RacingAReasonUpdate_KeepsBothChangesrunsSetKeepDisplayAwake(true)against a reason-only update over 3000 trials. Each trial uses a fresh controller, and two long-lived threads are released together by spinning on shared counters. It asserts that every trial ends with both changes. Starting a task per trial (the Decide and apply a Toggle under one lock, so concurrent toggles each flip once [patch] #31 Toggle-test style) staggers the two sides too much: with that design the old code passed 200/200, so the test uses long-lived threads instead. The threads are background threads and every wait has a 10 s timeout, so a failure can't hang the test host.SetRequest_WithAnUpdate_AppliesItToTheRequestInForceandSetRequest_WithAnUpdateThatReturnsNull_ThrowsAndKeepsTheRequestcover the new overload directly.SetKeepDisplayAwakebody and kept everything else. The race test then failed on three runs out of three, losing a change in 8 to 13 of every 2000 trials (4 cores). With the fix, the full suite passes on repeated runs (32/32, about 6 s).Generated by Claude Code