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 package atomic
6 7 import "unsafe"
8 9 // A Bool is an atomic boolean value.
10 // The zero value is false.
11 //
12 // Bool must not be copied after first use.
13 type Bool struct {
14 _ noCopy
15 v uint32
16 }
17 18 // Load atomically loads and returns the value stored in x.
19 func (x *Bool) Load() bool { return LoadUint32(&x.v) != 0 }
20 21 // Store atomically stores val into x.
22 func (x *Bool) Store(val bool) { StoreUint32(&x.v, b32(val)) }
23 24 // Swap atomically stores new into x and returns the previous value.
25 func (x *Bool) Swap(new bool) (old bool) { return SwapUint32(&x.v, b32(new)) != 0 }
26 27 // CompareAndSwap executes the compare-and-swap operation for the boolean value x.
28 func (x *Bool) CompareAndSwap(old, new bool) (swapped bool) {
29 return CompareAndSwapUint32(&x.v, b32(old), b32(new))
30 }
31 32 // b32 returns a uint32 0 or 1 representing b.
33 func b32(b bool) uint32 {
34 if b {
35 return 1
36 }
37 return 0
38 }
39 40 // For testing *Pointer[T]'s methods can be inlined.
41 // Keep in sync with cmd/compile/internal/test/inl_test.go:TestIntendedInlining.
42 var _ = &Pointer[int]{}
43 44 // A Pointer is an atomic pointer of type *T. The zero value is a nil *T.
45 //
46 // Pointer must not be copied after first use.
47 type Pointer[T any] struct {
48 // Mention *T in a field to disallow conversion between Pointer types.
49 // See go.dev/issue/56603 for more details.
50 // Use *T, not T, to avoid spurious recursive type definition errors.
51 _ [0]*T
52 53 _ noCopy
54 v unsafe.Pointer
55 }
56 57 // Load atomically loads and returns the value stored in x.
58 func (x *Pointer[T]) Load() *T { return (*T)(LoadPointer(&x.v)) }
59 60 // Store atomically stores val into x.
61 func (x *Pointer[T]) Store(val *T) { StorePointer(&x.v, unsafe.Pointer(val)) }
62 63 // Swap atomically stores new into x and returns the previous value.
64 func (x *Pointer[T]) Swap(new *T) (old *T) { return (*T)(SwapPointer(&x.v, unsafe.Pointer(new))) }
65 66 // CompareAndSwap executes the compare-and-swap operation for x.
67 func (x *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) {
68 return CompareAndSwapPointer(&x.v, unsafe.Pointer(old), unsafe.Pointer(new))
69 }
70 71 // An Int32 is an atomic int32. The zero value is zero.
72 //
73 // Int32 must not be copied after first use.
74 type Int32 struct {
75 _ noCopy
76 v int32
77 }
78 79 // Load atomically loads and returns the value stored in x.
80 func (x *Int32) Load() int32 { return LoadInt32(&x.v) }
81 82 // Store atomically stores val into x.
83 func (x *Int32) Store(val int32) { StoreInt32(&x.v, val) }
84 85 // Swap atomically stores new into x and returns the previous value.
86 func (x *Int32) Swap(new int32) (old int32) { return SwapInt32(&x.v, new) }
87 88 // CompareAndSwap executes the compare-and-swap operation for x.
89 func (x *Int32) CompareAndSwap(old, new int32) (swapped bool) {
90 return CompareAndSwapInt32(&x.v, old, new)
91 }
92 93 // Add atomically adds delta to x and returns the new value.
94 func (x *Int32) Add(delta int32) (new int32) { return AddInt32(&x.v, delta) }
95 96 // And atomically performs a bitwise AND operation on x using the bitmask
97 // provided as mask and returns the old value.
98 func (x *Int32) And(mask int32) (old int32) { return AndInt32(&x.v, mask) }
99 100 // Or atomically performs a bitwise OR operation on x using the bitmask
101 // provided as mask and returns the old value.
102 func (x *Int32) Or(mask int32) (old int32) { return OrInt32(&x.v, mask) }
103 104 // An Int64 is an atomic int64. The zero value is zero.
105 //
106 // Int64 must not be copied after first use.
107 type Int64 struct {
108 _ noCopy
109 _ align64
110 v int64
111 }
112 113 // Load atomically loads and returns the value stored in x.
114 func (x *Int64) Load() int64 { return LoadInt64(&x.v) }
115 116 // Store atomically stores val into x.
117 func (x *Int64) Store(val int64) { StoreInt64(&x.v, val) }
118 119 // Swap atomically stores new into x and returns the previous value.
120 func (x *Int64) Swap(new int64) (old int64) { return SwapInt64(&x.v, new) }
121 122 // CompareAndSwap executes the compare-and-swap operation for x.
123 func (x *Int64) CompareAndSwap(old, new int64) (swapped bool) {
124 return CompareAndSwapInt64(&x.v, old, new)
125 }
126 127 // Add atomically adds delta to x and returns the new value.
128 func (x *Int64) Add(delta int64) (new int64) { return AddInt64(&x.v, delta) }
129 130 // And atomically performs a bitwise AND operation on x using the bitmask
131 // provided as mask and returns the old value.
132 func (x *Int64) And(mask int64) (old int64) { return AndInt64(&x.v, mask) }
133 134 // Or atomically performs a bitwise OR operation on x using the bitmask
135 // provided as mask and returns the old value.
136 func (x *Int64) Or(mask int64) (old int64) { return OrInt64(&x.v, mask) }
137 138 // A Uint32 is an atomic uint32. The zero value is zero.
139 //
140 // Uint32 must not be copied after first use.
141 type Uint32 struct {
142 _ noCopy
143 v uint32
144 }
145 146 // Load atomically loads and returns the value stored in x.
147 func (x *Uint32) Load() uint32 { return LoadUint32(&x.v) }
148 149 // Store atomically stores val into x.
150 func (x *Uint32) Store(val uint32) { StoreUint32(&x.v, val) }
151 152 // Swap atomically stores new into x and returns the previous value.
153 func (x *Uint32) Swap(new uint32) (old uint32) { return SwapUint32(&x.v, new) }
154 155 // CompareAndSwap executes the compare-and-swap operation for x.
156 func (x *Uint32) CompareAndSwap(old, new uint32) (swapped bool) {
157 return CompareAndSwapUint32(&x.v, old, new)
158 }
159 160 // Add atomically adds delta to x and returns the new value.
161 func (x *Uint32) Add(delta uint32) (new uint32) { return AddUint32(&x.v, delta) }
162 163 // And atomically performs a bitwise AND operation on x using the bitmask
164 // provided as mask and returns the old value.
165 func (x *Uint32) And(mask uint32) (old uint32) { return AndUint32(&x.v, mask) }
166 167 // Or atomically performs a bitwise OR operation on x using the bitmask
168 // provided as mask and returns the old value.
169 func (x *Uint32) Or(mask uint32) (old uint32) { return OrUint32(&x.v, mask) }
170 171 // A Uint64 is an atomic uint64. The zero value is zero.
172 //
173 // Uint64 must not be copied after first use.
174 type Uint64 struct {
175 _ noCopy
176 _ align64
177 v uint64
178 }
179 180 // Load atomically loads and returns the value stored in x.
181 func (x *Uint64) Load() uint64 { return LoadUint64(&x.v) }
182 183 // Store atomically stores val into x.
184 func (x *Uint64) Store(val uint64) { StoreUint64(&x.v, val) }
185 186 // Swap atomically stores new into x and returns the previous value.
187 func (x *Uint64) Swap(new uint64) (old uint64) { return SwapUint64(&x.v, new) }
188 189 // CompareAndSwap executes the compare-and-swap operation for x.
190 func (x *Uint64) CompareAndSwap(old, new uint64) (swapped bool) {
191 return CompareAndSwapUint64(&x.v, old, new)
192 }
193 194 // Add atomically adds delta to x and returns the new value.
195 func (x *Uint64) Add(delta uint64) (new uint64) { return AddUint64(&x.v, delta) }
196 197 // And atomically performs a bitwise AND operation on x using the bitmask
198 // provided as mask and returns the old value.
199 func (x *Uint64) And(mask uint64) (old uint64) { return AndUint64(&x.v, mask) }
200 201 // Or atomically performs a bitwise OR operation on x using the bitmask
202 // provided as mask and returns the old value.
203 func (x *Uint64) Or(mask uint64) (old uint64) { return OrUint64(&x.v, mask) }
204 205 // A Uintptr is an atomic uintptr. The zero value is zero.
206 //
207 // Uintptr must not be copied after first use.
208 type Uintptr struct {
209 _ noCopy
210 v uintptr
211 }
212 213 // Load atomically loads and returns the value stored in x.
214 func (x *Uintptr) Load() uintptr { return LoadUintptr(&x.v) }
215 216 // Store atomically stores val into x.
217 func (x *Uintptr) Store(val uintptr) { StoreUintptr(&x.v, val) }
218 219 // Swap atomically stores new into x and returns the previous value.
220 func (x *Uintptr) Swap(new uintptr) (old uintptr) { return SwapUintptr(&x.v, new) }
221 222 // CompareAndSwap executes the compare-and-swap operation for x.
223 func (x *Uintptr) CompareAndSwap(old, new uintptr) (swapped bool) {
224 return CompareAndSwapUintptr(&x.v, old, new)
225 }
226 227 // Add atomically adds delta to x and returns the new value.
228 func (x *Uintptr) Add(delta uintptr) (new uintptr) { return AddUintptr(&x.v, delta) }
229 230 // And atomically performs a bitwise AND operation on x using the bitmask
231 // provided as mask and returns the old value.
232 func (x *Uintptr) And(mask uintptr) (old uintptr) { return AndUintptr(&x.v, mask) }
233 234 // Or atomically performs a bitwise OR operation on x using the bitmask
235 // provided as mask and returns the old value.
236 func (x *Uintptr) Or(mask uintptr) (old uintptr) { return OrUintptr(&x.v, mask) }
237 238 // noCopy may be added to structs which must not be copied
239 // after the first use.
240 //
241 // See https://golang.org/issues/8005#issuecomment-190753527
242 // for details.
243 //
244 // Note that it must not be embedded, due to the Lock and Unlock methods.
245 type noCopy struct{}
246 247 // Lock is a no-op used by -copylocks checker from `go vet`.
248 func (*noCopy) Lock() {}
249 func (*noCopy) Unlock() {}
250 251 // align64 may be added to structs that must be 64-bit aligned.
252 // This struct is recognized by a special case in the compiler
253 // and will not work if copied to any other package.
254 type align64 struct{}
255