locking.go 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package cache
  4. import "sync"
  5. // Locking wraps an inner Cache implementation with a mutex, making it
  6. // safe for concurrent use. All methods are serialized on the same mutex.
  7. type Locking[K comparable, V any, C Cache[K, V]] struct {
  8. sync.Mutex
  9. inner C
  10. }
  11. // NewLocking creates a new Locking cache wrapping inner.
  12. func NewLocking[K comparable, V any, C Cache[K, V]](inner C) *Locking[K, V, C] {
  13. return &Locking[K, V, C]{inner: inner}
  14. }
  15. // Get implements Cache.
  16. //
  17. // The cache's mutex is held for the entire duration of this function,
  18. // including while the FillFunc is being called. This function is not
  19. // reentrant; attempting to call Get from a FillFunc will deadlock.
  20. func (c *Locking[K, V, C]) Get(key K, f FillFunc[V]) (V, error) {
  21. c.Lock()
  22. defer c.Unlock()
  23. return c.inner.Get(key, f)
  24. }
  25. // Forget implements Cache.
  26. func (c *Locking[K, V, C]) Forget(key K) {
  27. c.Lock()
  28. defer c.Unlock()
  29. c.inner.Forget(key)
  30. }
  31. // Empty implements Cache.
  32. func (c *Locking[K, V, C]) Empty() {
  33. c.Lock()
  34. defer c.Unlock()
  35. c.inner.Empty()
  36. }