pomerium/internal/atomicutil/value.go
Ryota 711394d51f
Fix typo, add more test cases for atomicutil, and mention about atomic.Pointer migration (#5736)
I found the `atomicutil` package used throughout the code base, but it
seems to predate the addition of `atomic.Pointer[T]`. Potentially this
should allow us to remove the package altogether and use stdlib directly
instead. But I went ahead with starting with adding simple test cases
first, so that we have better test coverage across the code base.

Also, I added an example of how `atomicutil` usage may be problematic in
some specific scenario compared to how it's implemented with
`atomic.Pointer[T]`. Not to mention, there is some performance gain of
not using the direct casting with its generic support. (Though this is
probably a minor one and the code clarity is a benefit we may want to
keep rather than using other atomic values such as `atomic.Bool`.)

---------

Co-authored-by: Kenneth Jenkins <51246568+kenjenkins@users.noreply.github.com>
2025-07-22 15:11:30 -07:00

47 lines
916 B
Go

// Package atomicutil contains functions for working with the atomic package.
package atomicutil
import "sync/atomic"
// Value is a generic atomic.Value.
type Value[T any] struct {
value atomic.Value
}
// NewValue creates a new Value.
func NewValue[T any](init T) *Value[T] {
v := new(Value[T])
v.value.Store(init)
return v
}
// Load loads the value atomically.
func (v *Value[T]) Load() T {
var def T
if v == nil {
return def
}
cur := v.value.Load()
if cur == nil {
return def
}
return cur.(T)
}
// Store stores the value atomically.
func (v *Value[T]) Store(val T) {
v.value.Store(val)
}
// Swap swaps the value atomically.
func (v *Value[T]) Swap(val T) T {
old, _ := v.value.Swap(val).(T)
return old
}
// CompareAndSwap swaps the value atomically, and returns true if the swap
// was executed.
func (v *Value[T]) CompareAndSwap(old, n T) bool {
return v.value.CompareAndSwap(old, n)
}