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 }