github.com/kelleygo/clashcore@v1.0.2/common/atomic/value.go (about) 1 package atomic 2 3 import ( 4 "encoding/json" 5 "sync/atomic" 6 ) 7 8 func DefaultValue[T any]() T { 9 var defaultValue T 10 return defaultValue 11 } 12 13 type TypedValue[T any] struct { 14 _ noCopy 15 value atomic.Value 16 } 17 18 // tValue is a struct with determined type to resolve atomic.Value usages with interface types 19 // https://github.com/golang/go/issues/22550 20 // 21 // The intention to have an atomic value store for errors. However, running this code panics: 22 // panic: sync/atomic: store of inconsistently typed value into Value 23 // This is because atomic.Value requires that the underlying concrete type be the same (which is a reasonable expectation for its implementation). 24 // When going through the atomic.Value.Store method call, the fact that both these are of the error interface is lost. 25 type tValue[T any] struct { 26 value T 27 } 28 29 func (t *TypedValue[T]) Load() T { 30 value := t.value.Load() 31 if value == nil { 32 return DefaultValue[T]() 33 } 34 return value.(tValue[T]).value 35 } 36 37 func (t *TypedValue[T]) Store(value T) { 38 t.value.Store(tValue[T]{value}) 39 } 40 41 func (t *TypedValue[T]) Swap(new T) T { 42 old := t.value.Swap(tValue[T]{new}) 43 if old == nil { 44 return DefaultValue[T]() 45 } 46 return old.(tValue[T]).value 47 } 48 49 func (t *TypedValue[T]) CompareAndSwap(old, new T) bool { 50 return t.value.CompareAndSwap(tValue[T]{old}, tValue[T]{new}) 51 } 52 53 func (t *TypedValue[T]) MarshalJSON() ([]byte, error) { 54 return json.Marshal(t.Load()) 55 } 56 57 func (t *TypedValue[T]) UnmarshalJSON(b []byte) error { 58 var v T 59 if err := json.Unmarshal(b, &v); err != nil { 60 return err 61 } 62 t.Store(v) 63 return nil 64 } 65 66 func NewTypedValue[T any](t T) (v TypedValue[T]) { 67 v.Store(t) 68 return 69 } 70 71 type noCopy struct{} 72 73 // Lock is a no-op used by -copylocks checker from `go vet`. 74 func (*noCopy) Lock() {} 75 func (*noCopy) Unlock() {}