Repository navigation
refactor: replace single-variable mutexes with atomic types - #3330
Conversation
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🟢 APPROVE
The refactor correctly replaces single-variable mutexes with atomic types across all three files:
- **** → with in for idempotency and in the wait goroutine — both uses are correct.
- **** → — nil checks are in place before dereferencing the loaded pointer.
- **** → in — nil is handled correctly.
The removed mutexes each guarded exactly one mutable field (as described), so no other fields are left unprotected. The changes are behavior-preserving and idiomatic Go.
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🟢 APPROVE
The refactor correctly replaces single-variable mutexes with atomic types across all three files. No bugs were found in the changed code.
lspSession.closed→atomic.Bool:CompareAndSwap(false, true)inClose()correctly preserves idempotency;Load()in the wait goroutine is the right read primitive.lastSelectedID→atomic.Pointer[modelsdev.ID]: nil is handled before dereferencing the loaded pointer.current→atomic.Pointer[string]inagentRouter: nil is handled correctly on load.
The removed mutexes each guarded exactly one mutable field, so no other fields are left without synchronization. The changes are behavior-preserving and idiomatic Go.
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🟢 APPROVE
The refactor correctly replaces mutex-protected single fields with sync/atomic types across all three files.
lspSession.closed → atomic.Bool: The CompareAndSwap(false, true) in Close() correctly preserves idempotency. The happens-before ordering (CAS → processCancel → process exit → cmd.Wait()) ensures the wait goroutine observes closed=true after a signal-induced exit.
Client.lastSelectedID → atomic.Pointer[modelsdev.ID]: Taking the address of the local selectedID variable correctly heap-escapes it via the Go compiler. The nil-check on Load() properly mirrors the old zero-value behavior on first call.
agentRouter.current → atomic.Pointer[string]: newAgentRouter always calls Store before the struct is shared, and the nil guard in Name() is a correct and harmless safety net.
No bugs introduced. All changes are behavior-preserving.
docker-agent 1.93.0 Created-by: HarmonybrewBot Commit-by: HarmonybrewBot Merged-by: HarmonybrewBot Description: Created by `brew bump` --- Created with `brew bump-formula-pr`.<details> <summary>release notes</summary> <pre>This release adds OpenRouter as a built-in provider, introduces per-model gateway bypass support, and allows a dedicated model for session compaction, alongside several internal refactoring improvements. ## What's New - Adds OpenRouter as a first-class built-in provider; when `OPENROUTER_API_KEY` is set, the provider is auto-detected and its base URL resolved automatically - Adds a `compaction_model` field to allow a dedicated model for session summary generation, separate from the primary agent model - Adds a `bypass_models_gateway` boolean field on a per-model basis, allowing specific models to connect directly to their provider instead of routing through the configured models gateway ## Technical Changes - Replaces mutex usage with atomic types (`atomic.Bool`, `atomic.Pointer`) for single mutable fields in several structs - Replaces package-level global variables with explicit parameters or struct fields to enable parallel-safe testing across several packages (`toolinstall`, `runtime`, `mcp`, `notification`, `tui`, `cmd/root`) - Adds a concurrency group to the PR review trigger CI workflow to prevent duplicate reviews for the same PR --- ## What's Changed * docs: update CHANGELOG.md for v1.92.0 by @docker-read-write[bot] in docker/docker-agent#3331 * refactor: replace single-variable mutexes with atomic types by @dgageot in docker/docker-agent#3330 * ci: add concurrency group to pr-review-trigger to prevent duplicate reviews by @derekmisler in docker/docker-agent#3334 * refactor: replace test-overridden globals with parallel-safe injection by @dgageot in docker/docker-agent#3332 * feat(compaction): allow a dedicated model for session summary generation by @Sayt-0 in docker/docker-agent#3335 * feat: add OpenRouter provider by @dgageot in docker/docker-agent#3337 * feat: add per-model bypass_models_gateway option by @dgageot in docker/docker-agent#3338 **Full Changelog**: docker/docker-agent@v1.92.0...v1.93.0 </pre> <p>View the full release notes at <a href="https://github.com/docker/docker-agent/releases/tag/v1.93.0">https://github.com/docker/docker-agent/releases/tag/v1.93.0</a>.</p> </details> <hr> See merge request: Harmonybrew/homebrew-core!13152
Each of the three structs changed here used a
sync.Mutexorsync.RWMutexto protect exactly one mutable field — all other fields were written once at construction and never changed afterward. When a mutex guards a single variable, the standard library'ssync/atomicpackage offers a simpler and more self-documenting fit: the data and its synchronization are expressed as one value rather than two separate declarations.lspSessioninpkg/tools/builtin/lsp/lsp_lifecycle.gohad aclosed boolprotected by a plain mutex. It is now anatomic.Bool, withCompareAndSwapinClose()to preserve idempotency andLoad()in the wait goroutine to check the flag.Clientinpkg/model/provider/rulebased/client.gohad alastSelectedIDof typemodelsdev.IDbehind anRWMutex; it is now anatomic.Pointer[modelsdev.ID].agentRouterinpkg/runtime/agent_router.gohad acurrent stringbehind anRWMutex; it is now anatomic.Pointer[string].All changes are behavior-preserving. The suite passes under
go test -raceand the linter reports no new issues.