@@ -11,19 +11,7 @@ func DefaultValue[T any]() T {
1111}
1212
1313type 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
14+ value atomic.Pointer [T ]
2715}
2816
2917func (t * TypedValue [T ]) Load () T {
@@ -36,27 +24,36 @@ func (t *TypedValue[T]) LoadOk() (_ T, ok bool) {
3624 if value == nil {
3725 return DefaultValue [T ](), false
3826 }
39- return value .( tValue [ T ]). value , true
27+ return * value , true
4028}
4129
4230func (t * TypedValue [T ]) Store (value T ) {
43- t .value .Store (tValue [ T ]{ value } )
31+ t .value .Store (& value )
4432}
4533
4634func (t * TypedValue [T ]) Swap (new T ) T {
47- old := t .value .Swap (tValue [ T ]{ new } )
35+ old := t .value .Swap (& new )
4836 if old == nil {
4937 return DefaultValue [T ]()
5038 }
51- return old .( tValue [ T ]). value
39+ return * old
5240}
5341
5442func (t * TypedValue [T ]) CompareAndSwap (old , new T ) bool {
55- return t .value .CompareAndSwap (tValue [T ]{old }, tValue [T ]{new }) ||
56- // In the edge-case where [atomic.Value.Store] is uninitialized
57- // and trying to compare with the zero value of T,
58- // then compare-and-swap with the nil any value.
59- (any (old ) == any (DefaultValue [T ]()) && t .value .CompareAndSwap (any (nil ), tValue [T ]{new }))
43+ for {
44+ currentP := t .value .Load ()
45+ currentValue := DefaultValue [T ]()
46+ if currentP != nil {
47+ currentValue = * currentP
48+ }
49+ // Compare old and current via runtime equality check.
50+ if any (currentValue ) != any (old ) {
51+ return false
52+ }
53+ if t .value .CompareAndSwap (currentP , & new ) {
54+ return true
55+ }
56+ }
6057}
6158
6259func (t * TypedValue [T ]) MarshalJSON () ([]byte , error ) {
@@ -89,9 +86,3 @@ func NewTypedValue[T any](t T) (v TypedValue[T]) {
8986 v .Store (t )
9087 return
9188}
92-
93- type noCopy struct {}
94-
95- // Lock is a no-op used by -copylocks checker from `go vet`.
96- func (* noCopy ) Lock () {}
97- func (* noCopy ) Unlock () {}
0 commit comments