From e382e4cee6a79aae5ba639b930306e8cc2f08f4f Mon Sep 17 00:00:00 2001 From: Andrew Dunham Date: Tue, 19 Mar 2024 18:22:42 -0400 Subject: [PATCH] syncs: add Swap method To mimic sync.Map.Swap, sync/atomic.Value.Swap, etc. Updates tailscale/corp#1297 Signed-off-by: Andrew Dunham Change-Id: If7627da1bce8b552873b21d7e5ebb98904e9a650 --- syncs/syncs.go | 11 +++++++++++ syncs/syncs_test.go | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/syncs/syncs.go b/syncs/syncs.go index ef180784c..66ca69b60 100644 --- a/syncs/syncs.go +++ b/syncs/syncs.go @@ -271,6 +271,17 @@ func (m *Map[K, V]) Clear() { clear(m.m) } +// Swap stores the value for the provided key, and returns the previous value +// (if any). If there was no previous value set, a zero value will be returned. +func (m *Map[K, V]) Swap(key K, value V) (oldValue V) { + m.mu.Lock() + defer m.mu.Unlock() + + oldValue = m.m[key] + mak.Set(&m.m, key, value) + return oldValue +} + // WaitGroup is identical to [sync.WaitGroup], // but provides a Go method to start a goroutine. type WaitGroup struct{ sync.WaitGroup } diff --git a/syncs/syncs_test.go b/syncs/syncs_test.go index d6b993f67..4e99979d6 100644 --- a/syncs/syncs_test.go +++ b/syncs/syncs_test.go @@ -169,4 +169,15 @@ func TestMap(t *testing.T) { t.Errorf("Len after Clear want=0 got=%d", m.Len()) } }) + + t.Run("Swap", func(t *testing.T) { + var m Map[string, string] + m.Store("hello", "world") + if got, want := m.Swap("hello", "world2"), "world"; got != want { + t.Errorf("got old value %q, want %q", got, want) + } + if got := m.Swap("empty", "foo"); got != "" { + t.Errorf("got old value %q, want empty string", got) + } + }) }