github.com/metacubex/mihomo@v1.18.5/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() {}