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  }