Files
.bencher
.github
appc
atomicfile
chirp
client
clientupdate
cmd
control
derp
disco
docs
doctor
drive
envknob
gokrazy
health
hostinfo
internal
ipn
jsondb
k8s-operator
kube
licenses
log
logpolicy
logtail
metrics
net
omit
packages
paths
portlist
posture
prober
proxymap
publicapi
release
safesocket
safeweb
scripts
sessionrecording
smallzstd
ssh
syncs
tailcfg
taildrop
tempfork
tka
tool
tsconst
tsd
tsnet
tstest
tstime
tsweb
types
util
cache
cache_test.go
interface.go
locking.go
none.go
single.go
cibuild
clientmetric
cloudenv
cmpver
codegen
cstruct
ctxkey
deephash
dirwalk
dnsname
execqueue
expvarx
fastuuid
goroutines
groupmember
hashx
httphdr
httpm
jsonutil
limiter
lineread
linuxfw
lru
mak
multierr
must
nocasemaps
osdiag
osshare
osuser
pidowner
pool
precompress
progresstracking
quarantine
race
racebuild
rands
reload
ringbuffer
set
singleflight
slicesx
syspolicy
sysresources
systemd
testenv
topk
truncate
uniq
vizerror
winutil
zstdframe
version
wf
wgengine
words
.gitattributes
.gitignore
.golangci.yml
ALPINE.txt
AUTHORS
CODEOWNERS
CODE_OF_CONDUCT.md
Dockerfile
Dockerfile.base
LICENSE
Makefile
PATENTS
README.md
SECURITY.md
VERSION.txt
api.md
build_dist.sh
build_docker.sh
flake.lock
flake.nix
go.mod
go.mod.sri
go.sum
go.toolchain.branch
go.toolchain.rev
gomod_test.go
header.txt
pkgdoc_test.go
pull-toolchain.sh
shell.nix
staticcheck.conf
update-flake.sh
version-embed.go
version_test.go
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 

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()
}