1 // Copyright (c) 2016 Uber Technologies, Inc.
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // Package atomic provides simple wrappers around numerics to enforce atomic
31 // Int32 is an atomic wrapper around an int32.
32 type Int32 struct{ v int32 }
34 // NewInt32 creates an Int32.
35 func NewInt32(i int32) *Int32 {
39 // Load atomically loads the wrapped value.
40 func (i *Int32) Load() int32 {
41 return atomic.LoadInt32(&i.v)
44 // Add atomically adds to the wrapped int32 and returns the new value.
45 func (i *Int32) Add(n int32) int32 {
46 return atomic.AddInt32(&i.v, n)
49 // Sub atomically subtracts from the wrapped int32 and returns the new value.
50 func (i *Int32) Sub(n int32) int32 {
51 return atomic.AddInt32(&i.v, -n)
54 // Inc atomically increments the wrapped int32 and returns the new value.
55 func (i *Int32) Inc() int32 {
59 // Dec atomically decrements the wrapped int32 and returns the new value.
60 func (i *Int32) Dec() int32 {
64 // CAS is an atomic compare-and-swap.
65 func (i *Int32) CAS(old, new int32) bool {
66 return atomic.CompareAndSwapInt32(&i.v, old, new)
69 // Store atomically stores the passed value.
70 func (i *Int32) Store(n int32) {
71 atomic.StoreInt32(&i.v, n)
74 // Swap atomically swaps the wrapped int32 and returns the old value.
75 func (i *Int32) Swap(n int32) int32 {
76 return atomic.SwapInt32(&i.v, n)
79 // Int64 is an atomic wrapper around an int64.
80 type Int64 struct{ v int64 }
82 // NewInt64 creates an Int64.
83 func NewInt64(i int64) *Int64 {
87 // Load atomically loads the wrapped value.
88 func (i *Int64) Load() int64 {
89 return atomic.LoadInt64(&i.v)
92 // Add atomically adds to the wrapped int64 and returns the new value.
93 func (i *Int64) Add(n int64) int64 {
94 return atomic.AddInt64(&i.v, n)
97 // Sub atomically subtracts from the wrapped int64 and returns the new value.
98 func (i *Int64) Sub(n int64) int64 {
99 return atomic.AddInt64(&i.v, -n)
102 // Inc atomically increments the wrapped int64 and returns the new value.
103 func (i *Int64) Inc() int64 {
107 // Dec atomically decrements the wrapped int64 and returns the new value.
108 func (i *Int64) Dec() int64 {
112 // CAS is an atomic compare-and-swap.
113 func (i *Int64) CAS(old, new int64) bool {
114 return atomic.CompareAndSwapInt64(&i.v, old, new)
117 // Store atomically stores the passed value.
118 func (i *Int64) Store(n int64) {
119 atomic.StoreInt64(&i.v, n)
122 // Swap atomically swaps the wrapped int64 and returns the old value.
123 func (i *Int64) Swap(n int64) int64 {
124 return atomic.SwapInt64(&i.v, n)
127 // Uint32 is an atomic wrapper around an uint32.
128 type Uint32 struct{ v uint32 }
130 // NewUint32 creates a Uint32.
131 func NewUint32(i uint32) *Uint32 {
135 // Load atomically loads the wrapped value.
136 func (i *Uint32) Load() uint32 {
137 return atomic.LoadUint32(&i.v)
140 // Add atomically adds to the wrapped uint32 and returns the new value.
141 func (i *Uint32) Add(n uint32) uint32 {
142 return atomic.AddUint32(&i.v, n)
145 // Sub atomically subtracts from the wrapped uint32 and returns the new value.
146 func (i *Uint32) Sub(n uint32) uint32 {
147 return atomic.AddUint32(&i.v, ^(n - 1))
150 // Inc atomically increments the wrapped uint32 and returns the new value.
151 func (i *Uint32) Inc() uint32 {
155 // Dec atomically decrements the wrapped int32 and returns the new value.
156 func (i *Uint32) Dec() uint32 {
160 // CAS is an atomic compare-and-swap.
161 func (i *Uint32) CAS(old, new uint32) bool {
162 return atomic.CompareAndSwapUint32(&i.v, old, new)
165 // Store atomically stores the passed value.
166 func (i *Uint32) Store(n uint32) {
167 atomic.StoreUint32(&i.v, n)
170 // Swap atomically swaps the wrapped uint32 and returns the old value.
171 func (i *Uint32) Swap(n uint32) uint32 {
172 return atomic.SwapUint32(&i.v, n)
175 // Uint64 is an atomic wrapper around a uint64.
176 type Uint64 struct{ v uint64 }
178 // NewUint64 creates a Uint64.
179 func NewUint64(i uint64) *Uint64 {
183 // Load atomically loads the wrapped value.
184 func (i *Uint64) Load() uint64 {
185 return atomic.LoadUint64(&i.v)
188 // Add atomically adds to the wrapped uint64 and returns the new value.
189 func (i *Uint64) Add(n uint64) uint64 {
190 return atomic.AddUint64(&i.v, n)
193 // Sub atomically subtracts from the wrapped uint64 and returns the new value.
194 func (i *Uint64) Sub(n uint64) uint64 {
195 return atomic.AddUint64(&i.v, ^(n - 1))
198 // Inc atomically increments the wrapped uint64 and returns the new value.
199 func (i *Uint64) Inc() uint64 {
203 // Dec atomically decrements the wrapped uint64 and returns the new value.
204 func (i *Uint64) Dec() uint64 {
208 // CAS is an atomic compare-and-swap.
209 func (i *Uint64) CAS(old, new uint64) bool {
210 return atomic.CompareAndSwapUint64(&i.v, old, new)
213 // Store atomically stores the passed value.
214 func (i *Uint64) Store(n uint64) {
215 atomic.StoreUint64(&i.v, n)
218 // Swap atomically swaps the wrapped uint64 and returns the old value.
219 func (i *Uint64) Swap(n uint64) uint64 {
220 return atomic.SwapUint64(&i.v, n)
223 // Bool is an atomic Boolean.
224 type Bool struct{ v uint32 }
226 // NewBool creates a Bool.
227 func NewBool(initial bool) *Bool {
228 return &Bool{boolToInt(initial)}
231 // Load atomically loads the Boolean.
232 func (b *Bool) Load() bool {
233 return truthy(atomic.LoadUint32(&b.v))
236 // CAS is an atomic compare-and-swap.
237 func (b *Bool) CAS(old, new bool) bool {
238 return atomic.CompareAndSwapUint32(&b.v, boolToInt(old), boolToInt(new))
241 // Store atomically stores the passed value.
242 func (b *Bool) Store(new bool) {
243 atomic.StoreUint32(&b.v, boolToInt(new))
246 // Swap sets the given value and returns the previous value.
247 func (b *Bool) Swap(new bool) bool {
248 return truthy(atomic.SwapUint32(&b.v, boolToInt(new)))
251 // Toggle atomically negates the Boolean and returns the previous value.
252 func (b *Bool) Toggle() bool {
253 return truthy(atomic.AddUint32(&b.v, 1) - 1)
256 func truthy(n uint32) bool {
260 func boolToInt(b bool) uint32 {
267 // Float64 is an atomic wrapper around float64.
268 type Float64 struct {
272 // NewFloat64 creates a Float64.
273 func NewFloat64(f float64) *Float64 {
274 return &Float64{math.Float64bits(f)}
277 // Load atomically loads the wrapped value.
278 func (f *Float64) Load() float64 {
279 return math.Float64frombits(atomic.LoadUint64(&f.v))
282 // Store atomically stores the passed value.
283 func (f *Float64) Store(s float64) {
284 atomic.StoreUint64(&f.v, math.Float64bits(s))
287 // Add atomically adds to the wrapped float64 and returns the new value.
288 func (f *Float64) Add(s float64) float64 {
298 // Sub atomically subtracts from the wrapped float64 and returns the new value.
299 func (f *Float64) Sub(s float64) float64 {
303 // CAS is an atomic compare-and-swap.
304 func (f *Float64) CAS(old, new float64) bool {
305 return atomic.CompareAndSwapUint64(&f.v, math.Float64bits(old), math.Float64bits(new))
308 // Duration is an atomic wrapper around time.Duration
309 // https://godoc.org/time#Duration
310 type Duration struct {
314 // NewDuration creates a Duration.
315 func NewDuration(d time.Duration) *Duration {
316 return &Duration{v: *NewInt64(int64(d))}
319 // Load atomically loads the wrapped value.
320 func (d *Duration) Load() time.Duration {
321 return time.Duration(d.v.Load())
324 // Store atomically stores the passed value.
325 func (d *Duration) Store(n time.Duration) {
329 // Add atomically adds to the wrapped time.Duration and returns the new value.
330 func (d *Duration) Add(n time.Duration) time.Duration {
331 return time.Duration(d.v.Add(int64(n)))
334 // Sub atomically subtracts from the wrapped time.Duration and returns the new value.
335 func (d *Duration) Sub(n time.Duration) time.Duration {
336 return time.Duration(d.v.Sub(int64(n)))
339 // Swap atomically swaps the wrapped time.Duration and returns the old value.
340 func (d *Duration) Swap(n time.Duration) time.Duration {
341 return time.Duration(d.v.Swap(int64(n)))
344 // CAS is an atomic compare-and-swap.
345 func (d *Duration) CAS(old, new time.Duration) bool {
346 return d.v.CAS(int64(old), int64(new))
349 // Value shadows the type of the same name from sync/atomic
350 // https://godoc.org/sync/atomic#Value
351 type Value struct{ atomic.Value }