github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/atomic/types_compat.go (about)

     1  // Copyright 2022 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build !go1.19
     6  
     7  package atomic
     8  
     9  import (
    10  	"sync/atomic"
    11  	"unsafe"
    12  )
    13  
    14  // A Bool is an atomic boolean value.
    15  // The zero value is false.
    16  type Bool struct {
    17  	_ noCopy
    18  	v uint32
    19  }
    20  
    21  // Load atomically loads and returns the value stored in x.
    22  func (x *Bool) Load() bool { return atomic.LoadUint32(&x.v) != 0 }
    23  
    24  // Store atomically stores val into x.
    25  func (x *Bool) Store(val bool) { atomic.StoreUint32(&x.v, b32(val)) }
    26  
    27  // Swap atomically stores new into x and returns the previous value.
    28  func (x *Bool) Swap(new bool) (old bool) { return atomic.SwapUint32(&x.v, b32(new)) != 0 }
    29  
    30  // CompareAndSwap executes the compare-and-swap operation for the boolean value x.
    31  func (x *Bool) CompareAndSwap(old, new bool) (swapped bool) {
    32  	return atomic.CompareAndSwapUint32(&x.v, b32(old), b32(new))
    33  }
    34  
    35  // b32 returns a uint32 0 or 1 representing b.
    36  func b32(b bool) uint32 {
    37  	if b {
    38  		return 1
    39  	}
    40  	return 0
    41  }
    42  
    43  // A Pointer is an atomic pointer of type *T. The zero value is a nil *T.
    44  type Pointer[T any] struct {
    45  	// Mention *T in a field to disallow conversion between Pointer types.
    46  	// See go.dev/issue/56603 for more details.
    47  	// Use *T, not T, to avoid spurious recursive type definition errors.
    48  	_ [0]*T
    49  
    50  	_ noCopy
    51  	v unsafe.Pointer
    52  }
    53  
    54  // Load atomically loads and returns the value stored in x.
    55  func (x *Pointer[T]) Load() *T { return (*T)(atomic.LoadPointer(&x.v)) }
    56  
    57  // Store atomically stores val into x.
    58  func (x *Pointer[T]) Store(val *T) { atomic.StorePointer(&x.v, unsafe.Pointer(val)) }
    59  
    60  // Swap atomically stores new into x and returns the previous value.
    61  func (x *Pointer[T]) Swap(new *T) (old *T) {
    62  	return (*T)(atomic.SwapPointer(&x.v, unsafe.Pointer(new)))
    63  }
    64  
    65  // CompareAndSwap executes the compare-and-swap operation for x.
    66  func (x *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) {
    67  	return atomic.CompareAndSwapPointer(&x.v, unsafe.Pointer(old), unsafe.Pointer(new))
    68  }
    69  
    70  // An Int32 is an atomic int32. The zero value is zero.
    71  type Int32 struct {
    72  	_ noCopy
    73  	v int32
    74  }
    75  
    76  // Load atomically loads and returns the value stored in x.
    77  func (x *Int32) Load() int32 { return atomic.LoadInt32(&x.v) }
    78  
    79  // Store atomically stores val into x.
    80  func (x *Int32) Store(val int32) { atomic.StoreInt32(&x.v, val) }
    81  
    82  // Swap atomically stores new into x and returns the previous value.
    83  func (x *Int32) Swap(new int32) (old int32) { return atomic.SwapInt32(&x.v, new) }
    84  
    85  // CompareAndSwap executes the compare-and-swap operation for x.
    86  func (x *Int32) CompareAndSwap(old, new int32) (swapped bool) {
    87  	return atomic.CompareAndSwapInt32(&x.v, old, new)
    88  }
    89  
    90  // Add atomically adds delta to x and returns the new value.
    91  func (x *Int32) Add(delta int32) (new int32) { return atomic.AddInt32(&x.v, delta) }
    92  
    93  // An Int64 is an atomic int64. The zero value is zero.
    94  type Int64 struct {
    95  	_ noCopy
    96  	v int64
    97  }
    98  
    99  // Load atomically loads and returns the value stored in x.
   100  func (x *Int64) Load() int64 { return atomic.LoadInt64(&x.v) }
   101  
   102  // Store atomically stores val into x.
   103  func (x *Int64) Store(val int64) { atomic.StoreInt64(&x.v, val) }
   104  
   105  // Swap atomically stores new into x and returns the previous value.
   106  func (x *Int64) Swap(new int64) (old int64) { return atomic.SwapInt64(&x.v, new) }
   107  
   108  // CompareAndSwap executes the compare-and-swap operation for x.
   109  func (x *Int64) CompareAndSwap(old, new int64) (swapped bool) {
   110  	return atomic.CompareAndSwapInt64(&x.v, old, new)
   111  }
   112  
   113  // Add atomically adds delta to x and returns the new value.
   114  func (x *Int64) Add(delta int64) (new int64) { return atomic.AddInt64(&x.v, delta) }
   115  
   116  // An Uint32 is an atomic uint32. The zero value is zero.
   117  type Uint32 struct {
   118  	_ noCopy
   119  	v uint32
   120  }
   121  
   122  // Load atomically loads and returns the value stored in x.
   123  func (x *Uint32) Load() uint32 { return atomic.LoadUint32(&x.v) }
   124  
   125  // Store atomically stores val into x.
   126  func (x *Uint32) Store(val uint32) { atomic.StoreUint32(&x.v, val) }
   127  
   128  // Swap atomically stores new into x and returns the previous value.
   129  func (x *Uint32) Swap(new uint32) (old uint32) { return atomic.SwapUint32(&x.v, new) }
   130  
   131  // CompareAndSwap executes the compare-and-swap operation for x.
   132  func (x *Uint32) CompareAndSwap(old, new uint32) (swapped bool) {
   133  	return atomic.CompareAndSwapUint32(&x.v, old, new)
   134  }
   135  
   136  // Add atomically adds delta to x and returns the new value.
   137  func (x *Uint32) Add(delta uint32) (new uint32) { return atomic.AddUint32(&x.v, delta) }
   138  
   139  // An Uint64 is an atomic uint64. The zero value is zero.
   140  type Uint64 struct {
   141  	_ noCopy
   142  	v uint64
   143  }
   144  
   145  // Load atomically loads and returns the value stored in x.
   146  func (x *Uint64) Load() uint64 { return atomic.LoadUint64(&x.v) }
   147  
   148  // Store atomically stores val into x.
   149  func (x *Uint64) Store(val uint64) { atomic.StoreUint64(&x.v, val) }
   150  
   151  // Swap atomically stores new into x and returns the previous value.
   152  func (x *Uint64) Swap(new uint64) (old uint64) { return atomic.SwapUint64(&x.v, new) }
   153  
   154  // CompareAndSwap executes the compare-and-swap operation for x.
   155  func (x *Uint64) CompareAndSwap(old, new uint64) (swapped bool) {
   156  	return atomic.CompareAndSwapUint64(&x.v, old, new)
   157  }
   158  
   159  // Add atomically adds delta to x and returns the new value.
   160  func (x *Uint64) Add(delta uint64) (new uint64) { return atomic.AddUint64(&x.v, delta) }
   161  
   162  // An Uintptr is an atomic uintptr. The zero value is zero.
   163  type Uintptr struct {
   164  	_ noCopy
   165  	v uintptr
   166  }
   167  
   168  // Load atomically loads and returns the value stored in x.
   169  func (x *Uintptr) Load() uintptr { return atomic.LoadUintptr(&x.v) }
   170  
   171  // Store atomically stores val into x.
   172  func (x *Uintptr) Store(val uintptr) { atomic.StoreUintptr(&x.v, val) }
   173  
   174  // Swap atomically stores new into x and returns the previous value.
   175  func (x *Uintptr) Swap(new uintptr) (old uintptr) { return atomic.SwapUintptr(&x.v, new) }
   176  
   177  // CompareAndSwap executes the compare-and-swap operation for x.
   178  func (x *Uintptr) CompareAndSwap(old, new uintptr) (swapped bool) {
   179  	return atomic.CompareAndSwapUintptr(&x.v, old, new)
   180  }
   181  
   182  // Add atomically adds delta to x and returns the new value.
   183  func (x *Uintptr) Add(delta uintptr) (new uintptr) { return atomic.AddUintptr(&x.v, delta) }
   184  
   185  // noCopy may be added to structs which must not be copied
   186  // after the first use.
   187  //
   188  // See https://golang.org/issues/8005#issuecomment-190753527
   189  // for details.
   190  //
   191  // Note that it must not be embedded, due to the Lock and Unlock methods.
   192  type noCopy struct{}
   193  
   194  // Lock is a no-op used by -copylocks checker from `go vet`.
   195  func (*noCopy) Lock()   {}
   196  func (*noCopy) Unlock() {}
   197  
   198  type Value = atomic.Value