diff --git a/syncs/syncs.go b/syncs/syncs.go index 79acd8654..7f193f24e 100644 --- a/syncs/syncs.go +++ b/syncs/syncs.go @@ -9,6 +9,7 @@ import ( "sync" "sync/atomic" + "golang.org/x/exp/maps" "tailscale.com/util/mak" ) @@ -227,6 +228,13 @@ func (m *Map[K, V]) Len() int { return len(m.m) } +// Clear removes all entries from the map. +func (m *Map[K, V]) Clear() { + m.mu.Lock() + defer m.mu.Unlock() + maps.Clear(m.m) +} + // 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 3532d84f6..bb289862b 100644 --- a/syncs/syncs_test.go +++ b/syncs/syncs_test.go @@ -137,4 +137,22 @@ func TestMap(t *testing.T) { t.Errorf("exactly one LoadOrStore should load") } }) + + t.Run("Clear", func(t *testing.T) { + var m Map[string, string] + _, _ = m.LoadOrStore("a", "1") + _, _ = m.LoadOrStore("b", "2") + _, _ = m.LoadOrStore("c", "3") + _, _ = m.LoadOrStore("d", "4") + _, _ = m.LoadOrStore("e", "5") + + if m.Len() != 5 { + t.Errorf("Len after loading want=5 got=%d", m.Len()) + } + + m.Clear() + if m.Len() != 0 { + t.Errorf("Len after Clear want=0 got=%d", m.Len()) + } + }) }