mirror of
https://github.com/pomerium/pomerium.git
synced 2025-07-29 06:29:19 +02:00
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>
47 lines
916 B
Go
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)
|
|
}
|