Source file src/runtime/internal/atomic/types.go
1 // Copyright 2021 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 // Int32 is an atomically accessed int32 value. 10 // 11 // An Int32 must not be copied. 12 type Int32 struct { 13 noCopy noCopy 14 value int32 15 } 16 17 // Load accesses and returns the value atomically. 18 func (i *Int32) Load() int32 { 19 return Loadint32(&i.value) 20 } 21 22 // Store updates the value atomically. 23 func (i *Int32) Store(value int32) { 24 Storeint32(&i.value, value) 25 } 26 27 // CompareAndSwap atomically compares i's value with old, 28 // and if they're equal, swaps i's value with new. 29 // 30 // Returns true if the operation succeeded. 31 func (i *Int32) CompareAndSwap(old, new int32) bool { 32 return Casint32(&i.value, old, new) 33 } 34 35 // Swap replaces i's value with new, returning 36 // i's value before the replacement. 37 func (i *Int32) Swap(new int32) int32 { 38 return Xchgint32(&i.value, new) 39 } 40 41 // Add adds delta to i atomically, returning 42 // the new updated value. 43 // 44 // This operation wraps around in the usual 45 // two's-complement way. 46 func (i *Int32) Add(delta int32) int32 { 47 return Xaddint32(&i.value, delta) 48 } 49 50 // Int64 is an atomically accessed int64 value. 51 // 52 // An Int64 must not be copied. 53 type Int64 struct { 54 noCopy noCopy 55 value int64 56 } 57 58 // Load accesses and returns the value atomically. 59 func (i *Int64) Load() int64 { 60 return Loadint64(&i.value) 61 } 62 63 // Store updates the value atomically. 64 func (i *Int64) Store(value int64) { 65 Storeint64(&i.value, value) 66 } 67 68 // CompareAndSwap atomically compares i's value with old, 69 // and if they're equal, swaps i's value with new. 70 // 71 // Returns true if the operation succeeded. 72 func (i *Int64) CompareAndSwap(old, new int64) bool { 73 return Casint64(&i.value, old, new) 74 } 75 76 // Swap replaces i's value with new, returning 77 // i's value before the replacement. 78 func (i *Int64) Swap(new int64) int64 { 79 return Xchgint64(&i.value, new) 80 } 81 82 // Add adds delta to i atomically, returning 83 // the new updated value. 84 // 85 // This operation wraps around in the usual 86 // two's-complement way. 87 func (i *Int64) Add(delta int64) int64 { 88 return Xaddint64(&i.value, delta) 89 } 90 91 // Uint8 is an atomically accessed uint8 value. 92 // 93 // A Uint8 must not be copied. 94 type Uint8 struct { 95 noCopy noCopy 96 value uint8 97 } 98 99 // Load accesses and returns the value atomically. 100 func (u *Uint8) Load() uint8 { 101 return Load8(&u.value) 102 } 103 104 // Store updates the value atomically. 105 func (u *Uint8) Store(value uint8) { 106 Store8(&u.value, value) 107 } 108 109 // And takes value and performs a bit-wise 110 // "and" operation with the value of u, storing 111 // the result into u. 112 // 113 // The full process is performed atomically. 114 func (u *Uint8) And(value uint8) { 115 And8(&u.value, value) 116 } 117 118 // Or takes value and performs a bit-wise 119 // "or" operation with the value of u, storing 120 // the result into u. 121 // 122 // The full process is performed atomically. 123 func (u *Uint8) Or(value uint8) { 124 Or8(&u.value, value) 125 } 126 127 // Uint32 is an atomically accessed uint32 value. 128 // 129 // A Uint32 must not be copied. 130 type Uint32 struct { 131 noCopy noCopy 132 value uint32 133 } 134 135 // Load accesses and returns the value atomically. 136 func (u *Uint32) Load() uint32 { 137 return Load(&u.value) 138 } 139 140 // LoadAcquire is a partially unsynchronized version 141 // of Load that relaxes ordering constraints. Other threads 142 // may observe operations that precede this operation to 143 // occur after it, but no operation that occurs after it 144 // on this thread can be observed to occur before it. 145 // 146 // WARNING: Use sparingly and with great care. 147 func (u *Uint32) LoadAcquire() uint32 { 148 return LoadAcq(&u.value) 149 } 150 151 // Store updates the value atomically. 152 func (u *Uint32) Store(value uint32) { 153 Store(&u.value, value) 154 } 155 156 // StoreRelease is a partially unsynchronized version 157 // of Store that relaxes ordering constraints. Other threads 158 // may observe operations that occur after this operation to 159 // precede it, but no operation that precedes it 160 // on this thread can be observed to occur after it. 161 // 162 // WARNING: Use sparingly and with great care. 163 func (u *Uint32) StoreRelease(value uint32) { 164 StoreRel(&u.value, value) 165 } 166 167 // CompareAndSwap atomically compares u's value with old, 168 // and if they're equal, swaps u's value with new. 169 // 170 // Returns true if the operation succeeded. 171 func (u *Uint32) CompareAndSwap(old, new uint32) bool { 172 return Cas(&u.value, old, new) 173 } 174 175 // CompareAndSwapRelease is a partially unsynchronized version 176 // of Cas that relaxes ordering constraints. Other threads 177 // may observe operations that occur after this operation to 178 // precede it, but no operation that precedes it 179 // on this thread can be observed to occur after it. 180 // 181 // Returns true if the operation succeeded. 182 // 183 // WARNING: Use sparingly and with great care. 184 func (u *Uint32) CompareAndSwapRelease(old, new uint32) bool { 185 return CasRel(&u.value, old, new) 186 } 187 188 // Swap replaces u's value with new, returning 189 // u's value before the replacement. 190 func (u *Uint32) Swap(value uint32) uint32 { 191 return Xchg(&u.value, value) 192 } 193 194 // And takes value and performs a bit-wise 195 // "and" operation with the value of u, storing 196 // the result into u. 197 // 198 // The full process is performed atomically. 199 func (u *Uint32) And(value uint32) { 200 And(&u.value, value) 201 } 202 203 // Or takes value and performs a bit-wise 204 // "or" operation with the value of u, storing 205 // the result into u. 206 // 207 // The full process is performed atomically. 208 func (u *Uint32) Or(value uint32) { 209 Or(&u.value, value) 210 } 211 212 // Add adds delta to u atomically, returning 213 // the new updated value. 214 // 215 // This operation wraps around in the usual 216 // two's-complement way. 217 func (u *Uint32) Add(delta int32) uint32 { 218 return Xadd(&u.value, delta) 219 } 220 221 // Uint64 is an atomically accessed uint64 value. 222 // 223 // A Uint64 must not be copied. 224 type Uint64 struct { 225 noCopy noCopy 226 value uint64 227 } 228 229 // Load accesses and returns the value atomically. 230 func (u *Uint64) Load() uint64 { 231 return Load64(&u.value) 232 } 233 234 // Store updates the value atomically. 235 func (u *Uint64) Store(value uint64) { 236 Store64(&u.value, value) 237 } 238 239 // CompareAndSwap atomically compares u's value with old, 240 // and if they're equal, swaps u's value with new. 241 // 242 // Returns true if the operation succeeded. 243 func (u *Uint64) CompareAndSwap(old, new uint64) bool { 244 return Cas64(&u.value, old, new) 245 } 246 247 // Swap replaces u's value with new, returning 248 // u's value before the replacement. 249 func (u *Uint64) Swap(value uint64) uint64 { 250 return Xchg64(&u.value, value) 251 } 252 253 // Add adds delta to u atomically, returning 254 // the new updated value. 255 // 256 // This operation wraps around in the usual 257 // two's-complement way. 258 func (u *Uint64) Add(delta int64) uint64 { 259 return Xadd64(&u.value, delta) 260 } 261 262 // Uintptr is an atomically accessed uintptr value. 263 // 264 // A Uintptr must not be copied. 265 type Uintptr struct { 266 noCopy noCopy 267 value uintptr 268 } 269 270 // Load accesses and returns the value atomically. 271 func (u *Uintptr) Load() uintptr { 272 return Loaduintptr(&u.value) 273 } 274 275 // LoadAcquire is a partially unsynchronized version 276 // of Load that relaxes ordering constraints. Other threads 277 // may observe operations that precede this operation to 278 // occur after it, but no operation that occurs after it 279 // on this thread can be observed to occur before it. 280 // 281 // WARNING: Use sparingly and with great care. 282 func (u *Uintptr) LoadAcquire() uintptr { 283 return LoadAcquintptr(&u.value) 284 } 285 286 // Store updates the value atomically. 287 func (u *Uintptr) Store(value uintptr) { 288 Storeuintptr(&u.value, value) 289 } 290 291 // StoreRelease is a partially unsynchronized version 292 // of Store that relaxes ordering constraints. Other threads 293 // may observe operations that occur after this operation to 294 // precede it, but no operation that precedes it 295 // on this thread can be observed to occur after it. 296 // 297 // WARNING: Use sparingly and with great care. 298 func (u *Uintptr) StoreRelease(value uintptr) { 299 StoreReluintptr(&u.value, value) 300 } 301 302 // CompareAndSwap atomically compares u's value with old, 303 // and if they're equal, swaps u's value with new. 304 // 305 // Returns true if the operation succeeded. 306 func (u *Uintptr) CompareAndSwap(old, new uintptr) bool { 307 return Casuintptr(&u.value, old, new) 308 } 309 310 // Swap replaces u's value with new, returning 311 // u's value before the replacement. 312 func (u *Uintptr) Swap(value uintptr) uintptr { 313 return Xchguintptr(&u.value, value) 314 } 315 316 // Add adds delta to u atomically, returning 317 // the new updated value. 318 // 319 // This operation wraps around in the usual 320 // two's-complement way. 321 func (u *Uintptr) Add(delta uintptr) uintptr { 322 return Xadduintptr(&u.value, delta) 323 } 324 325 // Float64 is an atomically accessed float64 value. 326 // 327 // A Float64 must not be copied. 328 type Float64 struct { 329 u Uint64 330 } 331 332 // Load accesses and returns the value atomically. 333 func (f *Float64) Load() float64 { 334 r := f.u.Load() 335 return *(*float64)(unsafe.Pointer(&r)) 336 } 337 338 // Store updates the value atomically. 339 func (f *Float64) Store(value float64) { 340 f.u.Store(*(*uint64)(unsafe.Pointer(&value))) 341 } 342 343 // UnsafePointer is an atomically accessed unsafe.Pointer value. 344 // 345 // Note that because of the atomicity guarantees, stores to values 346 // of this type never trigger a write barrier, and the relevant 347 // methods are suffixed with "NoWB" to indicate that explicitly. 348 // As a result, this type should be used carefully, and sparingly, 349 // mostly with values that do not live in the Go heap anyway. 350 // 351 // An UnsafePointer must not be copied. 352 type UnsafePointer struct { 353 noCopy noCopy 354 value unsafe.Pointer 355 } 356 357 // Load accesses and returns the value atomically. 358 func (u *UnsafePointer) Load() unsafe.Pointer { 359 return Loadp(unsafe.Pointer(&u.value)) 360 } 361 362 // StoreNoWB updates the value atomically. 363 // 364 // WARNING: As the name implies this operation does *not* 365 // perform a write barrier on value, and so this operation may 366 // hide pointers from the GC. Use with care and sparingly. 367 // It is safe to use with values not found in the Go heap. 368 func (u *UnsafePointer) StoreNoWB(value unsafe.Pointer) { 369 StorepNoWB(unsafe.Pointer(&u.value), value) 370 } 371 372 // CompareAndSwapNoWB atomically (with respect to other methods) 373 // compares u's value with old, and if they're equal, 374 // swaps u's value with new. 375 // 376 // Returns true if the operation succeeded. 377 // 378 // WARNING: As the name implies this operation does *not* 379 // perform a write barrier on value, and so this operation may 380 // hide pointers from the GC. Use with care and sparingly. 381 // It is safe to use with values not found in the Go heap. 382 func (u *UnsafePointer) CompareAndSwapNoWB(old, new unsafe.Pointer) bool { 383 return Casp1(&u.value, old, new) 384 } 385 386 // noCopy may be embedded into structs which must not be copied 387 // after the first use. 388 // 389 // See https://golang.org/issues/8005#issuecomment-190753527 390 // for details. 391 type noCopy struct{} 392 393 // Lock is a no-op used by -copylocks checker from `go vet`. 394 func (*noCopy) Lock() {} 395 func (*noCopy) Unlock() {} 396