type.mx raw

   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