tailscale/util/cache/locking.go
Andrew Dunham 9fd29f15c7 util/cache: add package for general-purpose caching
This package allows caching arbitrary key/value pairs in-memory, along
with an interface implemented by the cache types.

Extracted from #7493

Signed-off-by: Andrew Dunham <andrew@du.nham.ca>
Change-Id: Ic8ca820927c456721cf324a0c8f3882a57752cc9
2023-12-07 18:19:38 -05:00

44 lines
1.1 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package cache
import "sync"
// Locking wraps an inner Cache implementation with a mutex, making it
// safe for concurrent use. All methods are serialized on the same mutex.
type Locking[K comparable, V any, C Cache[K, V]] struct {
sync.Mutex
inner C
}
// NewLocking creates a new Locking cache wrapping inner.
func NewLocking[K comparable, V any, C Cache[K, V]](inner C) *Locking[K, V, C] {
return &Locking[K, V, C]{inner: inner}
}
// Get implements Cache.
//
// The cache's mutex is held for the entire duration of this function,
// including while the FillFunc is being called. This function is not
// reentrant; attempting to call Get from a FillFunc will deadlock.
func (c *Locking[K, V, C]) Get(key K, f FillFunc[V]) (V, error) {
c.Lock()
defer c.Unlock()
return c.inner.Get(key, f)
}
// Forget implements Cache.
func (c *Locking[K, V, C]) Forget(key K) {
c.Lock()
defer c.Unlock()
c.inner.Forget(key)
}
// Empty implements Cache.
func (c *Locking[K, V, C]) Empty() {
c.Lock()
defer c.Unlock()
c.inner.Empty()
}