Browse Source

syncs: add Swap method

To mimic sync.Map.Swap, sync/atomic.Value.Swap, etc.

Updates tailscale/corp#1297

Signed-off-by: Andrew Dunham <[email protected]>
Change-Id: If7627da1bce8b552873b21d7e5ebb98904e9a650
Andrew Dunham 2 years ago
parent
commit
e382e4cee6
2 changed files with 22 additions and 0 deletions
  1. 11 0
      syncs/syncs.go
  2. 11 0
      syncs/syncs_test.go

+ 11 - 0
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 }

+ 11 - 0
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)
+		}
+	})
 }