Skip to content

feat: add top-level CompareAndSwap and CompareAndDelete functions #14

Description

@millerjp

feat: add top-level CompareAndSwap and CompareAndDelete functions

Summary

sync.Map gained CompareAndSwap and CompareAndDelete in Go 1.20. Both require the value type to be comparable. SyncMap[K comparable, V any] allows non-comparable V (slices, maps, functions), so these cannot be added as methods without a breaking constraint change. Per the v1.0.0 requirements doc and the user's architectural decision recorded in the plan, expose them as top-level generic functions with a tighter V comparable constraint — mirroring the stdlib pattern for constraint mismatches. The SyncMap type constraints stay unchanged.

Requirements

  1. Add in syncmap.go (or a new cas.go at the implementer's discretion — prefer syncmap.go to keep single-source rule):
    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)
    Each wraps the corresponding sync.Map method.
  2. Godoc on both functions: style matching docs: add doc.go and rewrite godoc on every exported symbol #11, calling out the V comparable constraint explicitly and naming the reason (sync.Map requires it).
  3. Unit tests in syncmap_test.go:
    • TestCompareAndSwap — subtests: match_swaps_returns_true, mismatch_no_swap_returns_false, missing_key_returns_false, zero_V_match_works.
    • TestCompareAndDelete — subtests: match_deletes_returns_true, mismatch_no_delete_returns_false, missing_key_returns_false, zero_V_match_works.
    • TestCompareAndSwapContention — 100 goroutines all attempting CAS on same key; exactly one succeeds per round.
  4. Coverage must not regress; new functions included in the 95% total.
  5. Apache 2.0 header; no AI-attribution tokens.
  6. CHANGELOG "Added" entry (lands in feat: add top-level CompareAndSwap and CompareAndDelete functions #14 if CHANGELOG exists, otherwise ships with this PR).

Acceptance Criteria

  1. grep -nE 'func CompareAndSwap\[' syncmap.go returns exactly one match.
  2. grep -nE 'func CompareAndDelete\[' syncmap.go returns exactly one match.
  3. Both functions compile against SyncMap[string, int] (comparable V) in the test file.
  4. A deliberate test-compile check with SyncMap[string, []byte] (non-comparable V) must produce a compile error — demonstrated by a comment in the test file referencing the Go playground or by including a commented-out line in a file-level comment block documenting that this is the expected failure mode. This is documentation, not a running test — it proves the constraint is load-bearing.
  5. go doc github.com/axonops/syncmap CompareAndSwap and … CompareAndDelete print non-empty godoc.
  6. go test -race -run 'TestCompareAndSwap|TestCompareAndDelete' -count=10 ./... passes stably.
  7. make coverage reports ≥95% including the new functions.
  8. make check passes end-to-end.
  9. CI on the PR green.

Testing Requirements

Documentation Requirements

Dependencies

Labels

  • enhancement
  • P0

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Blocks releaseenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions