vitess.io/vitess@v0.16.2/go/sync2/atomic.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package sync2
    18  
    19  import (
    20  	"math"
    21  	"sync"
    22  	"sync/atomic"
    23  	"time"
    24  )
    25  
    26  // AtomicInt32 is a wrapper with a simpler interface around atomic.(Add|Store|Load|CompareAndSwap)Int32 functions.
    27  type AtomicInt32 struct {
    28  	int32
    29  }
    30  
    31  // NewAtomicInt32 initializes a new AtomicInt32 with a given value.
    32  func NewAtomicInt32(n int32) AtomicInt32 {
    33  	return AtomicInt32{n}
    34  }
    35  
    36  // Add atomically adds n to the value.
    37  func (i *AtomicInt32) Add(n int32) int32 {
    38  	return atomic.AddInt32(&i.int32, n)
    39  }
    40  
    41  // Set atomically sets n as new value.
    42  func (i *AtomicInt32) Set(n int32) {
    43  	atomic.StoreInt32(&i.int32, n)
    44  }
    45  
    46  // Get atomically returns the current value.
    47  func (i *AtomicInt32) Get() int32 {
    48  	return atomic.LoadInt32(&i.int32)
    49  }
    50  
    51  // CompareAndSwap automatically swaps the old with the new value.
    52  func (i *AtomicInt32) CompareAndSwap(oldval, newval int32) (swapped bool) {
    53  	return atomic.CompareAndSwapInt32(&i.int32, oldval, newval)
    54  }
    55  
    56  // AtomicInt64 is a wrapper with a simpler interface around atomic.(Add|Store|Load|CompareAndSwap)Int64 functions.
    57  type AtomicInt64 struct {
    58  	int64
    59  }
    60  
    61  // NewAtomicInt64 initializes a new AtomicInt64 with a given value.
    62  func NewAtomicInt64(n int64) AtomicInt64 {
    63  	return AtomicInt64{n}
    64  }
    65  
    66  // Add atomically adds n to the value.
    67  func (i *AtomicInt64) Add(n int64) int64 {
    68  	return atomic.AddInt64(&i.int64, n)
    69  }
    70  
    71  // Set atomically sets n as new value.
    72  func (i *AtomicInt64) Set(n int64) {
    73  	atomic.StoreInt64(&i.int64, n)
    74  }
    75  
    76  // Get atomically returns the current value.
    77  func (i *AtomicInt64) Get() int64 {
    78  	return atomic.LoadInt64(&i.int64)
    79  }
    80  
    81  // CompareAndSwap automatically swaps the old with the new value.
    82  func (i *AtomicInt64) CompareAndSwap(oldval, newval int64) (swapped bool) {
    83  	return atomic.CompareAndSwapInt64(&i.int64, oldval, newval)
    84  }
    85  
    86  // AtomicFloat64 is a wrapper with a simpler interface around atomic.(Add|Store|Load|CompareAndSwap)Flat64 functions.
    87  type AtomicFloat64 struct {
    88  	uint64
    89  }
    90  
    91  // NewAtomicFloat64 initializes a new AtomicFloat64 with a given value.
    92  func NewAtomicFloat64(n float64) AtomicFloat64 {
    93  	return AtomicFloat64{math.Float64bits(n)}
    94  }
    95  
    96  // Set atomically sets n as new value.
    97  func (f *AtomicFloat64) Set(n float64) {
    98  	atomic.StoreUint64(&f.uint64, math.Float64bits(n))
    99  }
   100  
   101  // Get atomically returns the current value.
   102  func (f *AtomicFloat64) Get() float64 {
   103  	return math.Float64frombits(atomic.LoadUint64(&f.uint64))
   104  }
   105  
   106  // CompareAndSwap automatically swaps the old with the new value.
   107  func (f *AtomicFloat64) CompareAndSwap(oldval, newval float64) (swapped bool) {
   108  	return atomic.CompareAndSwapUint64(&f.uint64, math.Float64bits(oldval), math.Float64bits(newval))
   109  }
   110  
   111  // AtomicDuration is a wrapper with a simpler interface around atomic.(Add|Store|Load|CompareAndSwap)Int64 functions.
   112  type AtomicDuration struct {
   113  	int64
   114  }
   115  
   116  // NewAtomicDuration initializes a new AtomicDuration with a given value.
   117  func NewAtomicDuration(duration time.Duration) AtomicDuration {
   118  	return AtomicDuration{int64(duration)}
   119  }
   120  
   121  // Add atomically adds duration to the value.
   122  func (d *AtomicDuration) Add(duration time.Duration) time.Duration {
   123  	return time.Duration(atomic.AddInt64(&d.int64, int64(duration)))
   124  }
   125  
   126  // Set atomically sets duration as new value.
   127  func (d *AtomicDuration) Set(duration time.Duration) {
   128  	atomic.StoreInt64(&d.int64, int64(duration))
   129  }
   130  
   131  // Get atomically returns the current value.
   132  func (d *AtomicDuration) Get() time.Duration {
   133  	return time.Duration(atomic.LoadInt64(&d.int64))
   134  }
   135  
   136  // CompareAndSwap automatically swaps the old with the new value.
   137  func (d *AtomicDuration) CompareAndSwap(oldval, newval time.Duration) (swapped bool) {
   138  	return atomic.CompareAndSwapInt64(&d.int64, int64(oldval), int64(newval))
   139  }
   140  
   141  // AtomicBool gives an atomic boolean variable.
   142  type AtomicBool struct {
   143  	int32
   144  }
   145  
   146  // NewAtomicBool initializes a new AtomicBool with a given value.
   147  func NewAtomicBool(n bool) AtomicBool {
   148  	if n {
   149  		return AtomicBool{1}
   150  	}
   151  	return AtomicBool{0}
   152  }
   153  
   154  // Set atomically sets n as new value.
   155  func (i *AtomicBool) Set(n bool) {
   156  	if n {
   157  		atomic.StoreInt32(&i.int32, 1)
   158  	} else {
   159  		atomic.StoreInt32(&i.int32, 0)
   160  	}
   161  }
   162  
   163  // Get atomically returns the current value.
   164  func (i *AtomicBool) Get() bool {
   165  	return atomic.LoadInt32(&i.int32) != 0
   166  }
   167  
   168  // CompareAndSwap automatically swaps the old with the new value.
   169  func (i *AtomicBool) CompareAndSwap(o, n bool) bool {
   170  	var old, new int32
   171  	if o {
   172  		old = 1
   173  	}
   174  	if n {
   175  		new = 1
   176  	}
   177  	return atomic.CompareAndSwapInt32(&i.int32, old, new)
   178  }
   179  
   180  // AtomicString gives you atomic-style APIs for string, but
   181  // it's only a convenience wrapper that uses a mutex. So, it's
   182  // not as efficient as the rest of the atomic types.
   183  type AtomicString struct {
   184  	mu  sync.Mutex
   185  	str string
   186  }
   187  
   188  // Set atomically sets str as new value.
   189  func (s *AtomicString) Set(str string) {
   190  	s.mu.Lock()
   191  	s.str = str
   192  	s.mu.Unlock()
   193  }
   194  
   195  // Get atomically returns the current value.
   196  func (s *AtomicString) Get() string {
   197  	s.mu.Lock()
   198  	str := s.str
   199  	s.mu.Unlock()
   200  	return str
   201  }
   202  
   203  // CompareAndSwap automatically swaps the old with the new value.
   204  func (s *AtomicString) CompareAndSwap(oldval, newval string) (swqpped bool) {
   205  	s.mu.Lock()
   206  	defer s.mu.Unlock()
   207  	if s.str == oldval {
   208  		s.str = newval
   209  		return true
   210  	}
   211  	return false
   212  }