dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

atom.go (9816B)


      1 // Copyright (c) 2016 Uber Technologies, Inc.
      2 //
      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:
      9 //
     10 // The above copyright notice and this permission notice shall be included in
     11 // all copies or substantial portions of the Software.
     12 //
     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
     19 // THE SOFTWARE.
     20 
     21 // Package atomic provides simple wrappers around numerics to enforce atomic
     22 // access.
     23 
     24 package atom
     25 
     26 import (
     27 	"math"
     28 	"sync/atomic"
     29 	"time"
     30 )
     31 
     32 // Int32 is an atomic wrapper around an int32.
     33 type Int32 struct{ v int32 }
     34 
     35 // NewInt32 creates an Int32.
     36 func NewInt32(i int32) *Int32 {
     37 	return &Int32{i}
     38 }
     39 
     40 // Load atomically loads the wrapped value.
     41 func (i *Int32) Load() int32 {
     42 	return atomic.LoadInt32(&i.v)
     43 }
     44 
     45 // Add atomically adds to the wrapped int32 and returns the new value.
     46 func (i *Int32) Add(n int32) int32 {
     47 	return atomic.AddInt32(&i.v, n)
     48 }
     49 
     50 // Sub atomically subtracts from the wrapped int32 and returns the new value.
     51 func (i *Int32) Sub(n int32) int32 {
     52 	return atomic.AddInt32(&i.v, -n)
     53 }
     54 
     55 // Inc atomically increments the wrapped int32 and returns the new value.
     56 func (i *Int32) Inc() int32 {
     57 	return i.Add(1)
     58 }
     59 
     60 // Dec atomically decrements the wrapped int32 and returns the new value.
     61 func (i *Int32) Dec() int32 {
     62 	return i.Sub(1)
     63 }
     64 
     65 // CAS is an atomic compare-and-swap.
     66 func (i *Int32) CAS(old, new int32) bool {
     67 	return atomic.CompareAndSwapInt32(&i.v, old, new)
     68 }
     69 
     70 // Store atomically stores the passed value.
     71 func (i *Int32) Store(n int32) {
     72 	atomic.StoreInt32(&i.v, n)
     73 }
     74 
     75 // Swap atomically swaps the wrapped int32 and returns the old value.
     76 func (i *Int32) Swap(n int32) int32 {
     77 	return atomic.SwapInt32(&i.v, n)
     78 }
     79 
     80 // Int64 is an atomic wrapper around an int64.
     81 type Int64 struct{ v int64 }
     82 
     83 // NewInt64 creates an Int64.
     84 func NewInt64(i int64) *Int64 {
     85 	return &Int64{i}
     86 }
     87 
     88 // Load atomically loads the wrapped value.
     89 func (i *Int64) Load() int64 {
     90 	return atomic.LoadInt64(&i.v)
     91 }
     92 
     93 // Add atomically adds to the wrapped int64 and returns the new value.
     94 func (i *Int64) Add(n int64) int64 {
     95 	return atomic.AddInt64(&i.v, n)
     96 }
     97 
     98 // Sub atomically subtracts from the wrapped int64 and returns the new value.
     99 func (i *Int64) Sub(n int64) int64 {
    100 	return atomic.AddInt64(&i.v, -n)
    101 }
    102 
    103 // Inc atomically increments the wrapped int64 and returns the new value.
    104 func (i *Int64) Inc() int64 {
    105 	return i.Add(1)
    106 }
    107 
    108 // Dec atomically decrements the wrapped int64 and returns the new value.
    109 func (i *Int64) Dec() int64 {
    110 	return i.Sub(1)
    111 }
    112 
    113 // CAS is an atomic compare-and-swap.
    114 func (i *Int64) CAS(old, new int64) bool {
    115 	return atomic.CompareAndSwapInt64(&i.v, old, new)
    116 }
    117 
    118 // Store atomically stores the passed value.
    119 func (i *Int64) Store(n int64) {
    120 	atomic.StoreInt64(&i.v, n)
    121 }
    122 
    123 // Swap atomically swaps the wrapped int64 and returns the old value.
    124 func (i *Int64) Swap(n int64) int64 {
    125 	return atomic.SwapInt64(&i.v, n)
    126 }
    127 
    128 // Uint32 is an atomic wrapper around an uint32.
    129 type Uint32 struct{ v uint32 }
    130 
    131 // NewUint32 creates a Uint32.
    132 func NewUint32(i uint32) *Uint32 {
    133 	return &Uint32{i}
    134 }
    135 
    136 // Load atomically loads the wrapped value.
    137 func (i *Uint32) Load() uint32 {
    138 	return atomic.LoadUint32(&i.v)
    139 }
    140 
    141 // Add atomically adds to the wrapped uint32 and returns the new value.
    142 func (i *Uint32) Add(n uint32) uint32 {
    143 	return atomic.AddUint32(&i.v, n)
    144 }
    145 
    146 // Sub atomically subtracts from the wrapped uint32 and returns the new value.
    147 func (i *Uint32) Sub(n uint32) uint32 {
    148 	return atomic.AddUint32(&i.v, ^(n - 1))
    149 }
    150 
    151 // Inc atomically increments the wrapped uint32 and returns the new value.
    152 func (i *Uint32) Inc() uint32 {
    153 	return i.Add(1)
    154 }
    155 
    156 // Dec atomically decrements the wrapped int32 and returns the new value.
    157 func (i *Uint32) Dec() uint32 {
    158 	return i.Sub(1)
    159 }
    160 
    161 // CAS is an atomic compare-and-swap.
    162 func (i *Uint32) CAS(old, new uint32) bool {
    163 	return atomic.CompareAndSwapUint32(&i.v, old, new)
    164 }
    165 
    166 // Store atomically stores the passed value.
    167 func (i *Uint32) Store(n uint32) {
    168 	atomic.StoreUint32(&i.v, n)
    169 }
    170 
    171 // Swap atomically swaps the wrapped uint32 and returns the old value.
    172 func (i *Uint32) Swap(n uint32) uint32 {
    173 	return atomic.SwapUint32(&i.v, n)
    174 }
    175 
    176 // Uint64 is an atomic wrapper around a uint64.
    177 type Uint64 struct{ v uint64 }
    178 
    179 // NewUint64 creates a Uint64.
    180 func NewUint64(i uint64) *Uint64 {
    181 	return &Uint64{i}
    182 }
    183 
    184 // Load atomically loads the wrapped value.
    185 func (i *Uint64) Load() uint64 {
    186 	return atomic.LoadUint64(&i.v)
    187 }
    188 
    189 // Add atomically adds to the wrapped uint64 and returns the new value.
    190 func (i *Uint64) Add(n uint64) uint64 {
    191 	return atomic.AddUint64(&i.v, n)
    192 }
    193 
    194 // Sub atomically subtracts from the wrapped uint64 and returns the new value.
    195 func (i *Uint64) Sub(n uint64) uint64 {
    196 	return atomic.AddUint64(&i.v, ^(n - 1))
    197 }
    198 
    199 // Inc atomically increments the wrapped uint64 and returns the new value.
    200 func (i *Uint64) Inc() uint64 {
    201 	return i.Add(1)
    202 }
    203 
    204 // Dec atomically decrements the wrapped uint64 and returns the new value.
    205 func (i *Uint64) Dec() uint64 {
    206 	return i.Sub(1)
    207 }
    208 
    209 // CAS is an atomic compare-and-swap.
    210 func (i *Uint64) CAS(old, new uint64) bool {
    211 	return atomic.CompareAndSwapUint64(&i.v, old, new)
    212 }
    213 
    214 // Store atomically stores the passed value.
    215 func (i *Uint64) Store(n uint64) {
    216 	atomic.StoreUint64(&i.v, n)
    217 }
    218 
    219 // Swap atomically swaps the wrapped uint64 and returns the old value.
    220 func (i *Uint64) Swap(n uint64) uint64 {
    221 	return atomic.SwapUint64(&i.v, n)
    222 }
    223 
    224 // Bool is an atomic Boolean.
    225 type Bool struct{ v uint32 }
    226 
    227 // NewBool creates a Bool.
    228 func NewBool(initial bool) *Bool {
    229 	return &Bool{boolToInt(initial)}
    230 }
    231 
    232 // IsFalse return if the current value is true
    233 func (b *Bool) IsTrue() bool {
    234 	return b.Load()
    235 }
    236 
    237 // IsFalse return if the current value is false
    238 func (b *Bool) IsFalse() bool {
    239 	return !b.Load()
    240 }
    241 
    242 // SetTrue sets current value to true
    243 func (b *Bool) SetTrue() {
    244 	b.Store(true)
    245 }
    246 
    247 // SetFalse sets current value to false
    248 func (b *Bool) SetFalse() {
    249 	b.Store(false)
    250 }
    251 
    252 // Load atomically loads the Boolean.
    253 func (b *Bool) Load() bool {
    254 	return truthy(atomic.LoadUint32(&b.v))
    255 }
    256 
    257 // CAS is an atomic compare-and-swap.
    258 func (b *Bool) CAS(old, new bool) bool {
    259 	return atomic.CompareAndSwapUint32(&b.v, boolToInt(old), boolToInt(new))
    260 }
    261 
    262 // Store atomically stores the passed value.
    263 func (b *Bool) Store(new bool) {
    264 	atomic.StoreUint32(&b.v, boolToInt(new))
    265 }
    266 
    267 // Swap sets the given value and returns the previous value.
    268 func (b *Bool) Swap(new bool) bool {
    269 	return truthy(atomic.SwapUint32(&b.v, boolToInt(new)))
    270 }
    271 
    272 // Toggle atomically negates the Boolean and returns the previous value.
    273 func (b *Bool) Toggle() bool {
    274 	for {
    275 		old := b.Load()
    276 		if b.CAS(old, !old) {
    277 			return old
    278 		}
    279 	}
    280 }
    281 
    282 func truthy(n uint32) bool {
    283 	return n == 1
    284 }
    285 
    286 func boolToInt(b bool) uint32 {
    287 	if b {
    288 		return 1
    289 	}
    290 	return 0
    291 }
    292 
    293 // Float64 is an atomic wrapper around float64.
    294 type Float64 struct {
    295 	v uint64
    296 }
    297 
    298 // NewFloat64 creates a Float64.
    299 func NewFloat64(f float64) *Float64 {
    300 	return &Float64{math.Float64bits(f)}
    301 }
    302 
    303 // Load atomically loads the wrapped value.
    304 func (f *Float64) Load() float64 {
    305 	return math.Float64frombits(atomic.LoadUint64(&f.v))
    306 }
    307 
    308 // Store atomically stores the passed value.
    309 func (f *Float64) Store(s float64) {
    310 	atomic.StoreUint64(&f.v, math.Float64bits(s))
    311 }
    312 
    313 // Add atomically adds to the wrapped float64 and returns the new value.
    314 func (f *Float64) Add(s float64) float64 {
    315 	for {
    316 		old := f.Load()
    317 		new := old + s
    318 		if f.CAS(old, new) {
    319 			return new
    320 		}
    321 	}
    322 }
    323 
    324 // Sub atomically subtracts from the wrapped float64 and returns the new value.
    325 func (f *Float64) Sub(s float64) float64 {
    326 	return f.Add(-s)
    327 }
    328 
    329 // CAS is an atomic compare-and-swap.
    330 func (f *Float64) CAS(old, new float64) bool {
    331 	return atomic.CompareAndSwapUint64(&f.v, math.Float64bits(old), math.Float64bits(new))
    332 }
    333 
    334 // Duration is an atomic wrapper around time.Duration
    335 // https://godoc.org/time#Duration
    336 type Duration struct {
    337 	v Int64
    338 }
    339 
    340 // NewDuration creates a Duration.
    341 func NewDuration(d time.Duration) *Duration {
    342 	return &Duration{v: *NewInt64(int64(d))}
    343 }
    344 
    345 // Load atomically loads the wrapped value.
    346 func (d *Duration) Load() time.Duration {
    347 	return time.Duration(d.v.Load())
    348 }
    349 
    350 // Store atomically stores the passed value.
    351 func (d *Duration) Store(n time.Duration) {
    352 	d.v.Store(int64(n))
    353 }
    354 
    355 // Add atomically adds to the wrapped time.Duration and returns the new value.
    356 func (d *Duration) Add(n time.Duration) time.Duration {
    357 	return time.Duration(d.v.Add(int64(n)))
    358 }
    359 
    360 // Sub atomically subtracts from the wrapped time.Duration and returns the new value.
    361 func (d *Duration) Sub(n time.Duration) time.Duration {
    362 	return time.Duration(d.v.Sub(int64(n)))
    363 }
    364 
    365 // Swap atomically swaps the wrapped time.Duration and returns the old value.
    366 func (d *Duration) Swap(n time.Duration) time.Duration {
    367 	return time.Duration(d.v.Swap(int64(n)))
    368 }
    369 
    370 // CAS is an atomic compare-and-swap.
    371 func (d *Duration) CAS(old, new time.Duration) bool {
    372 	return d.v.CAS(int64(old), int64(new))
    373 }
    374 
    375 // Value shadows the type of the same name from sync/atomic
    376 // https://godoc.org/sync/atomic#Value
    377 type Value struct{ atomic.Value }