Skip to content

feat: add top-level CompareAndSwap and CompareAndDelete (#14)#22

Merged
millerjp merged 1 commit intomainfrom
feature/compare-and-swap
Apr 20, 2026
Merged

feat: add top-level CompareAndSwap and CompareAndDelete (#14)#22
millerjp merged 1 commit intomainfrom
feature/compare-and-swap

Conversation

@millerjp
Copy link
Copy Markdown

Summary

Adds top-level generic CompareAndSwap and CompareAndDelete functions, wrapping the corresponding sync.Map methods with a tighter V comparable constraint. SyncMap[K, V any] stays unchanged — non-comparable V types remain supported, and CAS operations reject them at compile time rather than panicking at runtime.

Closes #14.

Signatures

func CompareAndSwap[K, V comparable](m *SyncMap[K, V], key K, old, new V) (swapped bool)
func CompareAndDelete[K, V comparable](m *SyncMap[K, V], key K, old V) (deleted bool)

Verification

$ go doc github.com/axonops/syncmap CompareAndSwap | head -4
func CompareAndSwap[K, V comparable](m *SyncMap[K, V], key K, old, new V) (swapped bool)
    CompareAndSwap swaps the old and new values for key if the value currently
    stored in m is equal to old. The swapped result reports whether the swap was
    performed.

$ make check
… (all 14 gates green, coverage 100%, no vulnerabilities)

$ go test -race -count=10 -run 'TestCompareAnd' ./...
ok github.com/axonops/syncmap 1.290s

$ go test -bench='CompareAnd' -benchmem -run=^$ -benchtime=100000x ./...
BenchmarkCompareAndSwap-8            115.9 ns/op   56 B/op   1 allocs/op
BenchmarkCompareAndSwapMismatch-8     42.6 ns/op    7 B/op   0 allocs/op
BenchmarkCompareAndDelete-8           82.7 ns/op   48 B/op   1 allocs/op
BenchmarkCompareAndSwapParallel-8     46.7 ns/op   13 B/op   1 allocs/op

The 1 alloc/op on the success paths is the V→any boxing cost at the sync.Map boundary — the same cost raw sync.Map users pay. Target of "zero additional allocations beyond sync.Map itself" met.

Agent gates

  • Plan — one-commit scope, placement in syncmap.go between Delete and Range.
  • code-reviewer (pre) — approved; confirmed [K, V comparable] sugar semantics, named-return consistency, single-file rule.
  • test-writer (pre) — produced the initial test block; id starts at 1 so the stored-0 seed can't be mistaken for a winner.
  • security-reviewer (post) — approved with two IMPORTANTs (added godoc note on interface-V runtime panic; added comment on id-range invariant in the contention test).
  • performance-reviewer (post) — initially flagged missing benchmarks as BLOCKING; minimal CAS benchmarks added (syncmap_bench_test.go). Full public-method benchmark coverage remains with test: add benchmarks, runnable examples, and bench-regression infrastructure #15 as originally scoped.
  • go-quality — 8/8 PASS.
  • commit-message-reviewer — PASS.

Deferrals (tracked elsewhere)

Test plan

  • CI green
  • Coverage remains 100%
  • go doc CompareAndSwap renders the interface-V caveat

Wrap sync.Map.CompareAndSwap and sync.Map.CompareAndDelete as
package-level generic functions constrained to [K, V comparable].
SyncMap's own constraints stay [K comparable, V any] so
non-comparable value types remain supported; the CAS operations
simply reject them at compile time rather than panicking at runtime
inside sync.Map.

Godoc calls out the residual interface-V panic path (an interface V
holding a dynamic non-comparable value still panics inside sync.Map
comparison, matching Go's == semantics).

Tests cover the four happy and unhappy paths per function, plus a
100-goroutine contention test that asserts exactly one CAS wins and
the stored value matches the winner's id. Includes a comment block
demonstrating the non-comparable-V compile error next to the happy
path tests.

Seeds syncmap_bench_test.go with CAS + CAD benchmarks (contended and
uncontended). Full benchmark coverage across all public methods is
owned by #15.

CHANGELOG entry for the new functions is deferred to #17 (CHANGELOG
owner).

Coverage remains at 100%.
@millerjp millerjp merged commit 9385813 into main Apr 20, 2026
13 checks passed
@millerjp millerjp deleted the feature/compare-and-swap branch April 20, 2026 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add top-level CompareAndSwap and CompareAndDelete functions

1 participant