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