package syncs
import "tailscale.com/syncs"
Package syncs contains additional sync types and functionality.
Index ¶
- func AssertLocked(m *sync.Mutex)
- func AssertRLocked(rw *sync.RWMutex)
- func AssertWLocked(rw *sync.RWMutex)
- func ClosedChan() <-chan struct{}
- type AtomicValue
- func (v *AtomicValue[T]) CompareAndSwap(oldV, newV T) (swapped bool)
- func (v *AtomicValue[T]) Load() T
- func (v *AtomicValue[T]) LoadOk() (_ T, ok bool)
- func (v *AtomicValue[T]) Store(x T)
- func (v *AtomicValue[T]) Swap(x T) (old T)
- type Map
- func (m *Map[K, V]) All() iter.Seq2[K, V]
- func (m *Map[K, V]) Clear()
- func (m *Map[K, V]) Delete(key K)
- func (m *Map[K, V]) Keys() iter.Seq[K]
- func (m *Map[K, V]) Len() int
- func (m *Map[K, V]) Load(key K) (value V, loaded bool)
- func (m *Map[K, V]) LoadAndDelete(key K) (value V, loaded bool)
- func (m *Map[K, V]) LoadFunc(key K, f func(value V, loaded bool))
- func (m *Map[K, V]) LoadOrInit(key K, f func() V) (actual V, loaded bool)
- func (m *Map[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool)
- func (m *Map[K, V]) Store(key K, value V)
- func (m *Map[K, V]) Swap(key K, value V) (oldValue V)
- func (m *Map[K, V]) Values() iter.Seq[V]
- func (m *Map[K, V]) WithLock(f func(m2 map[K]V))
- type MutexValue
- func (m *MutexValue[T]) Load() T
- func (m *MutexValue[T]) Store(v T)
- func (m *MutexValue[T]) Swap(new T) (old T)
- func (m *MutexValue[T]) WithLock(f func(p *T))
- type Pool
- type Semaphore
- func NewSemaphore(n int) Semaphore
- func (s Semaphore) Acquire()
- func (s Semaphore) AcquireContext(ctx context.Context) bool
- func (s Semaphore) Release()
- func (s Semaphore) TryAcquire() bool
- type ShardValue
- func NewShardValue[T any]() *ShardValue[T]
- func (sp *ShardValue[T]) All(yield func(*T) bool)
- func (sp *ShardValue[T]) Len() int
- func (sp *ShardValue[T]) One(yield func(*T))
- type ShardedInt
- func NewShardedInt() *ShardedInt
- func (m *ShardedInt) Add(delta int64)
- func (m *ShardedInt) AppendText(b []byte) ([]byte, error)
- func (m *ShardedInt) GetDistribution() []int64
- func (m *ShardedInt) String() string
- func (m *ShardedInt) Value() int64
- type ShardedMap
- func NewShardedMap[K comparable, V any](shards int, shard func(K) int) *ShardedMap[K, V]
- func (m *ShardedMap[K, V]) Contains(key K) bool
- func (m *ShardedMap[K, V]) Delete(key K) (shrunk bool)
- func (m *ShardedMap[K, V]) Get(key K) (value V)
- func (m *ShardedMap[K, V]) GetOk(key K) (value V, ok bool)
- func (m *ShardedMap[K, V]) Len() int
- func (m *ShardedMap[K, V]) Mutate(key K, mutator func(oldValue V, oldValueExisted bool) (newValue V, keep bool)) (sizeDelta int)
- func (m *ShardedMap[K, V]) Set(key K, value V) (grew bool)
- type WaitGroup
- type WaitGroupChan
Functions ¶
func AssertLocked ¶
AssertLocked panics if m is not locked.
func AssertRLocked ¶
AssertRLocked panics if rw is not locked for reading or writing.
func AssertWLocked ¶
AssertWLocked panics if rw is not locked for writing.
func ClosedChan ¶
func ClosedChan() <-chan struct{}
ClosedChan returns a channel that's already closed.
Types ¶
type AtomicValue ¶
type AtomicValue[T any] struct { // contains filtered or unexported fields }
AtomicValue is the generic version of atomic.Value. See MutexValue for guidance on whether to use this type.
func (*AtomicValue[T]) CompareAndSwap ¶
func (v *AtomicValue[T]) CompareAndSwap(oldV, newV T) (swapped bool)
CompareAndSwap executes the compare-and-swap operation for the Value.
func (*AtomicValue[T]) Load ¶
func (v *AtomicValue[T]) Load() T
Load returns the value set by the most recent Store. It returns the zero value for T if the value is empty.
func (*AtomicValue[T]) LoadOk ¶
func (v *AtomicValue[T]) LoadOk() (_ T, ok bool)
LoadOk is like Load but returns a boolean indicating whether the value was loaded.
func (*AtomicValue[T]) Store ¶
func (v *AtomicValue[T]) Store(x T)
Store sets the value of the Value to x.
func (*AtomicValue[T]) Swap ¶
func (v *AtomicValue[T]) Swap(x T) (old T)
Swap stores new into Value and returns the previous value. It returns the zero value for T if the value is empty.
type Map ¶
type Map[K comparable, V any] struct { // contains filtered or unexported fields }
Map is a Go map protected by a sync.RWMutex. It is preferred over sync.Map for maps with entries that change at a relatively high frequency. This must not be shallow copied.
func (*Map[K, V]) All ¶
All iterates over all entries in the map in an undefined order. A read lock is held for the entire duration of the iteration. Use the [WithLock] method instead to mutate the map during iteration.
func (*Map[K, V]) Clear ¶
func (m *Map[K, V]) Clear()
Clear removes all entries from the map.
func (*Map[K, V]) Delete ¶
func (m *Map[K, V]) Delete(key K)
Delete deletes the entry identified by key.
func (*Map[K, V]) Keys ¶
Keys iterates over all keys in the map in an undefined order. A read lock is held for the entire duration of the iteration. Use the [WithLock] method instead to mutate the map during iteration.
func (*Map[K, V]) Len ¶
Len returns the length of the map.
func (*Map[K, V]) Load ¶
Load loads the value for the provided key and whether it was found.
func (*Map[K, V]) LoadAndDelete ¶
LoadAndDelete returns the value for the given key if it exists. It ensures that the map is cleared of any entry for the key.
func (*Map[K, V]) LoadFunc ¶
LoadFunc calls f with the value for the provided key regardless of whether the entry exists or not. The lock is held for the duration of the call to f.
func (*Map[K, V]) LoadOrInit ¶
LoadOrInit returns the value for the given key if it exists otherwise f is called to construct the value to be set. The lock is held for the duration to prevent duplicate initialization.
func (*Map[K, V]) LoadOrStore ¶
LoadOrStore returns the value for the given key if it exists otherwise it stores value.
func (*Map[K, V]) Store ¶
func (m *Map[K, V]) Store(key K, value V)
Store stores the value for the provided key.
func (*Map[K, V]) Swap ¶
func (m *Map[K, V]) Swap(key K, value V) (oldValue V)
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 (*Map[K, V]) Values ¶
Values iterates over all values in the map in an undefined order. A read lock is held for the entire duration of the iteration. Use the [WithLock] method instead to mutate the map during iteration.
func (*Map[K, V]) WithLock ¶
func (m *Map[K, V]) WithLock(f func(m2 map[K]V))
WithLock calls f with the underlying map. Use of m2 must not escape the duration of this call. The write-lock is held for the entire duration of this call.
type MutexValue ¶
type MutexValue[T any] struct { // contains filtered or unexported fields }
MutexValue is a value protected by a mutex.
AtomicValue, MutexValue, atomic.Pointer are similar and overlap in their use cases.
Use atomic.Pointer if the value being stored is a pointer and you only ever need load and store operations. An atomic pointer only occupies 1 word of memory.
Use MutexValue if the value being stored is not a pointer or you need the ability for a mutex to protect a set of operations performed on the value. A mutex-guarded value occupies 1 word of memory plus the memory representation of T.
AtomicValue is useful for non-pointer types that happen to have the memory layout of a single pointer. Examples include a map, channel, func, or a single field struct that contains any prior types. An atomic value occupies 2 words of memory. Consequently, Storing of non-pointer types always allocates.
Note that AtomicValue has the ability to report whether it was set while MutexValue lacks the ability to detect if the value was set and it happens to be the zero value of T. If such a use case is necessary, then you could consider wrapping T in [opt.Value].
func (*MutexValue[T]) Load ¶
func (m *MutexValue[T]) Load() T
Load returns a shallow copy of the underlying value.
func (*MutexValue[T]) Store ¶
func (m *MutexValue[T]) Store(v T)
Store stores a shallow copy of the provided value.
func (*MutexValue[T]) Swap ¶
func (m *MutexValue[T]) Swap(new T) (old T)
Swap stores new into m and returns the previous value.
func (*MutexValue[T]) WithLock ¶
func (m *MutexValue[T]) WithLock(f func(p *T))
WithLock calls f with a pointer to the value while holding the lock. The provided pointer must not leak beyond the scope of the call.
type Pool ¶
type Pool[T any] struct { // New optionally specifies a function to generate // a value when Get would otherwise return the zero value of T. // It may not be changed concurrently with calls to Get. New func() T // contains filtered or unexported fields }
Pool is the generic version of sync.Pool.
func (*Pool[T]) Get ¶
func (p *Pool[T]) Get() T
Get selects an arbitrary item from the Pool, removes it from the Pool, and returns it to the caller. See sync.Pool.Get.
func (*Pool[T]) Put ¶
func (p *Pool[T]) Put(x T)
Put adds x to the pool.
type Semaphore ¶
type Semaphore struct {
// contains filtered or unexported fields
}
Semaphore is a counting semaphore.
Use NewSemaphore to create one.
func NewSemaphore ¶
NewSemaphore returns a semaphore with resource count n.
func (Semaphore) Acquire ¶
func (s Semaphore) Acquire()
Acquire blocks until a resource is acquired.
func (Semaphore) AcquireContext ¶
AcquireContext reports whether the resource was acquired before the ctx was done.
func (Semaphore) Release ¶
func (s Semaphore) Release()
Release releases a resource.
func (Semaphore) TryAcquire ¶
TryAcquire reports, without blocking, whether the resource was acquired.
type ShardValue ¶
type ShardValue[T any] struct { // contains filtered or unexported fields }
ShardValue contains a value sharded over a set of shards. In order to be useful, T should be aligned to cache lines. Users must organize that usage in One and All is concurrency safe. The zero value is not safe for use; use NewShardValue.
func NewShardValue ¶
func NewShardValue[T any]() *ShardValue[T]
NewShardValue constructs a new ShardValue[T] with a shard per CPU.
func (*ShardValue[T]) All ¶
func (sp *ShardValue[T]) All(yield func(*T) bool)
All yields a pointer to the value in each shard.
func (*ShardValue[T]) Len ¶
func (sp *ShardValue[T]) Len() int
Len returns the number of shards.
func (*ShardValue[T]) One ¶
func (sp *ShardValue[T]) One(yield func(*T))
One yields a pointer to a single shard value with best-effort P-locality.
type ShardedInt ¶
type ShardedInt struct {
// contains filtered or unexported fields
}
ShardedInt provides a sharded atomic int64 value that optimizes high frequency (Mhz range and above) writes in highly parallel workloads. The zero value is not safe for use; use NewShardedInt. ShardedInt implements the expvar.Var interface.
func NewShardedInt ¶
func NewShardedInt() *ShardedInt
NewShardedInt returns a new ShardedInt.
func (*ShardedInt) Add ¶
func (m *ShardedInt) Add(delta int64)
Add adds delta to the value.
func (*ShardedInt) AppendText ¶
func (m *ShardedInt) AppendText(b []byte) ([]byte, error)
AppendText implements the encoding.TextAppender interface
func (*ShardedInt) GetDistribution ¶
func (m *ShardedInt) GetDistribution() []int64
GetDistribution returns the current value in each shard. This is intended for observability/debugging only.
func (*ShardedInt) String ¶
func (m *ShardedInt) String() string
String implements the expvar.Var interface
func (*ShardedInt) Value ¶
func (m *ShardedInt) Value() int64
Value returns the current value.
type ShardedMap ¶
type ShardedMap[K comparable, V any] struct { // contains filtered or unexported fields }
ShardedMap is a synchronized map[K]V, internally sharded by a user-defined K-sharding function.
The zero value is not safe for use; use NewShardedMap.
func NewShardedMap ¶
func NewShardedMap[K comparable, V any](shards int, shard func(K) int) *ShardedMap[K, V]
NewShardedMap returns a new ShardedMap with the given number of shards and sharding function.
The shard func must return a integer in the range [0, shards) purely deterministically based on the provided K.
func (*ShardedMap[K, V]) Contains ¶
func (m *ShardedMap[K, V]) Contains(key K) bool
Contains reports whether m contains key.
func (*ShardedMap[K, V]) Delete ¶
func (m *ShardedMap[K, V]) Delete(key K) (shrunk bool)
Delete removes key from m.
It reports whether the map size shrunk (that is, whether key was present in the map).
func (*ShardedMap[K, V]) Get ¶
func (m *ShardedMap[K, V]) Get(key K) (value V)
Get returns m[key] or the zero value of V if key is not present.
func (*ShardedMap[K, V]) GetOk ¶
func (m *ShardedMap[K, V]) GetOk(key K) (value V, ok bool)
GetOk returns m[key] and whether it was present.
func (*ShardedMap[K, V]) Len ¶
func (m *ShardedMap[K, V]) Len() int
Len returns the number of elements in m.
It does so by locking shards one at a time, so it's not particularly cheap, nor does it give a consistent snapshot of the map. It's mostly intended for metrics or testing.
func (*ShardedMap[K, V]) Mutate ¶
func (m *ShardedMap[K, V]) Mutate(key K, mutator func(oldValue V, oldValueExisted bool) (newValue V, keep bool)) (sizeDelta int)
Mutate atomically mutates m[k] by calling mutator.
The mutator function is called with the old value (or its zero value) and whether it existed in the map and it returns the new value and whether it should be set in the map (true) or deleted from the map (false).
It returns the change in size of the map as a result of the mutation, one of -1 (delete), 0 (change), or 1 (addition).
func (*ShardedMap[K, V]) Set ¶
func (m *ShardedMap[K, V]) Set(key K, value V) (grew bool)
Set sets m[key] = value.
present in m).
type WaitGroup ¶
WaitGroup is identical to sync.WaitGroup, but provides a Go method to start a goroutine.
func (*WaitGroup) Go ¶
func (wg *WaitGroup) Go(f func())
Go calls the given function in a new goroutine. It automatically increments the counter before execution and automatically decrements the counter after execution. It must not be called concurrently with Wait.
type WaitGroupChan ¶
type WaitGroupChan struct {
// contains filtered or unexported fields
}
WaitGroupChan is like a sync.WaitGroup, but has a chan that closes on completion that you can wait on. (This, you can only use the value once) Also, its zero value is not usable. Use the constructor.
func NewWaitGroupChan ¶
func NewWaitGroupChan() *WaitGroupChan
NewWaitGroupChan returns a new single-use WaitGroupChan.
func (*WaitGroupChan) Add ¶
func (wg *WaitGroupChan) Add(delta int)
Add adds delta, which may be negative, to the WaitGroupChan counter. If the counter becomes zero, all goroutines blocked on Wait or the Done chan are released. If the counter goes negative, Add panics.
Note that calls with a positive delta that occur when the counter is zero must happen before a Wait. Calls with a negative delta, or calls with a positive delta that start when the counter is greater than zero, may happen at any time. Typically this means the calls to Add should execute before the statement creating the goroutine or other event to be waited for.
func (*WaitGroupChan) Decr ¶
func (wg *WaitGroupChan) Decr()
Decr decrements the WaitGroup counter by one.
(It is like sync.WaitGroup's Done method, but we don't use Done in this type, because it's ambiguous between Context.Done and WaitGroup.Done. So we use DoneChan and Decr instead.)
func (*WaitGroupChan) DoneChan ¶
func (wg *WaitGroupChan) DoneChan() <-chan struct{}
DoneChan returns a channel that's closed on completion.
func (*WaitGroupChan) Wait ¶
func (wg *WaitGroupChan) Wait()
Wait blocks until the WaitGroupChan counter is zero.
Source Files ¶
locked.go pool.go shardedint.go shardedmap.go shardvalue.go shardvalue_go.go syncs.go
- Version
- v1.84.0 (latest)
- Published
- May 21, 2025
- Platform
- linux/amd64
- Imports
- 9 packages
- Last checked
- 1 day ago –
Tools for package owners.