mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
syncs: add LockFunc, LockValue, LockValues, and Mutex
The first 3 functions are helpers for running functions under the protection of a lock. The Mutex type is a wrapper over sync.Mutex with a Do method that runs a function under the protection of a lock. Updates #11038 Updates #cleanup Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
parent
c8f258a904
commit
2057205300
37
syncs/lock_example_test.go
Normal file
37
syncs/lock_example_test.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package syncs_test
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"tailscale.com/syncs"
|
||||
)
|
||||
|
||||
func ExampleLockFunc() {
|
||||
var nodesMu sync.Mutex
|
||||
var nodes []string
|
||||
syncs.LockFunc(&nodesMu, func() { nodes = append(nodes, "node123") })
|
||||
}
|
||||
|
||||
func ExampleLockValue() {
|
||||
var nodesMu sync.Mutex
|
||||
var nodes []string
|
||||
n := syncs.LockValue(&nodesMu, func() int { return len(nodes) })
|
||||
log.Printf("there are %d nodes", n)
|
||||
}
|
||||
|
||||
func ExampleLockValues() {
|
||||
var bufferMu sync.Mutex
|
||||
var buffer string
|
||||
b, err := syncs.LockValues(&bufferMu, func() ([]byte, error) {
|
||||
return hex.DecodeString(buffer)
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Decode error: %v", err)
|
||||
}
|
||||
log.Printf("decoded %d bytes", len(b))
|
||||
}
|
@ -304,3 +304,39 @@ func (wg *WaitGroup) Go(f func()) {
|
||||
f()
|
||||
}()
|
||||
}
|
||||
|
||||
// TODO(https://go.dev/issue/63941): LockFunc, LockValue, and LockValues
|
||||
// are helper functions proposed upstream. Their naming and signature
|
||||
// are based on the existing OnceFunc, OnceValue, and OnceValues
|
||||
// helper functions already in the [sync] package.
|
||||
|
||||
// LockFunc runs f while holding the lock.
|
||||
func LockFunc(lock sync.Locker, f func()) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
f()
|
||||
}
|
||||
|
||||
// LockValue runs f while holding the lock and returns the argument.
|
||||
func LockValue[T any](lock sync.Locker, f func() T) T {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
return f()
|
||||
}
|
||||
|
||||
// LockValues runs f while holding the lock and returns the arguments.
|
||||
func LockValues[T1, T2 any](lock sync.Locker, f func() (T1, T2)) (T1, T2) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
return f()
|
||||
}
|
||||
|
||||
// Mutex is identical to [sync.Mutex], but with additional methods.
|
||||
type Mutex struct{ sync.Mutex }
|
||||
|
||||
// Do runs f while holding the lock.
|
||||
func (m *Mutex) Do(f func()) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
f()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user