github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/atomic/typed.go (about) 1 package atomic 2 3 import ( 4 "sync/atomic" 5 6 "github.com/sagernet/sing/common" 7 ) 8 9 type TypedValue[T any] struct { 10 value atomic.Value 11 } 12 13 // typedValue is a struct with determined type to resolve atomic.Value usages with interface types 14 // https://github.com/golang/go/issues/22550 15 // 16 // The intention to have an atomic value store for errors. However, running this code panics: 17 // panic: sync/atomic: store of inconsistently typed value into Value 18 // This is because atomic.Value requires that the underlying concrete type be the same (which is a reasonable expectation for its implementation). 19 // When going through the atomic.Value.Store method call, the fact that both these are of the error interface is lost. 20 type typedValue[T any] struct { 21 value T 22 } 23 24 func (t *TypedValue[T]) Load() T { 25 value := t.value.Load() 26 if value == nil { 27 return common.DefaultValue[T]() 28 } 29 return value.(typedValue[T]).value 30 } 31 32 func (t *TypedValue[T]) Store(value T) { 33 t.value.Store(typedValue[T]{value}) 34 } 35 36 func (t *TypedValue[T]) Swap(new T) T { 37 old := t.value.Swap(typedValue[T]{new}) 38 if old == nil { 39 return common.DefaultValue[T]() 40 } 41 return old.(typedValue[T]).value 42 } 43 44 func (t *TypedValue[T]) CompareAndSwap(old, new T) bool { 45 return t.value.CompareAndSwap(typedValue[T]{old}, typedValue[T]{new}) 46 }