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  

View as plain text