summaryrefslogtreecommitdiffhomepage
path: root/syncs
diff options
context:
space:
mode:
authorMaisem Ali <maisem@tailscale.com>2022-08-04 10:51:21 -0700
committerMaisem Ali <maisem@gmail.com>2022-08-04 11:52:16 -0700
commitb75f81ec003c7ab39eb5b7c1aadc29df1d9a0932 (patch)
tree02928c9f0e35f8c79dfe7455898bbe54948e9472 /syncs
parent5055e00cf1e119e8242d655e48a5a9ba18136910 (diff)
downloadtailscale-b75f81ec003c7ab39eb5b7c1aadc29df1d9a0932.tar.xz
tailscale-b75f81ec003c7ab39eb5b7c1aadc29df1d9a0932.zip
syncs: add generic AtomicValue
Signed-off-by: Maisem Ali <maisem@tailscale.com>
Diffstat (limited to 'syncs')
-rw-r--r--syncs/syncs.go43
1 files changed, 43 insertions, 0 deletions
diff --git a/syncs/syncs.go b/syncs/syncs.go
index af9943632..1728a5df4 100644
--- a/syncs/syncs.go
+++ b/syncs/syncs.go
@@ -21,6 +21,49 @@ func initClosedChan() <-chan struct{} {
return ch
}
+// AtomicValue is the generic version of atomic.Value.
+type AtomicValue[T any] struct {
+ v atomic.Value
+}
+
+// Load returns the value set by the most recent Store.
+// It returns the zero value for T if the value is empty.
+func (v *AtomicValue[T]) Load() T {
+ x, _ := v.LoadOk()
+ return x
+}
+
+// LoadOk is like Load but returns a boolean indicating whether the value was
+// loaded.
+func (v *AtomicValue[T]) LoadOk() (_ T, ok bool) {
+ x := v.v.Load()
+ if x != nil {
+ return x.(T), true
+ }
+ var zero T
+ return zero, false
+}
+
+// Store sets the value of the Value to x.
+func (v *AtomicValue[T]) Store(x T) {
+ v.v.Store(x)
+}
+
+// Swap stores new into Value and returns the previous value.
+// It returns the zero value for T if the value is empty.
+func (v *AtomicValue[T]) Swap(x T) (old T) {
+ oldV := v.v.Swap(x)
+ if oldV != nil {
+ return oldV.(T)
+ }
+ return old
+}
+
+// CompareAndSwap executes the compare-and-swap operation for the Value.
+func (v *AtomicValue[T]) CompareAndSwap(oldV, newV T) (swapped bool) {
+ return v.v.CompareAndSwap(oldV, newV)
+}
+
// 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)