go-ml.dev/pkg/base@v0.0.0-20200610162856-60c38abac71b/fu/atomic.go (about) 1 package fu 2 3 import ( 4 "sync/atomic" 5 ) 6 7 /* 8 AtomicCounter - hm, yes it's atomic counter 9 */ 10 type AtomicCounter struct { 11 Value uint64 12 } 13 14 /* 15 PostInc increments counter and returns OLD value 16 */ 17 func (c *AtomicCounter) PostInc() uint64 { 18 for { 19 v := atomic.LoadUint64(&c.Value) 20 if atomic.CompareAndSwapUint64(&c.Value, v, v+1) { 21 return v 22 } 23 } 24 } 25 26 /* 27 Dec decrements counter and returns NEW value 28 */ 29 func (c *AtomicCounter) Dec() uint64 { 30 for { 31 v := atomic.LoadUint64(&c.Value) 32 if v == 0 { 33 panic("counter underflow") 34 } 35 if atomic.CompareAndSwapUint64(&c.Value, v, v-1) { 36 return v - 1 37 } 38 } 39 } 40 41 /* 42 AtomicFlag - hm, yes it's atomic flag 43 */ 44 type AtomicFlag struct { 45 Value int32 46 } 47 48 /* 49 Clear switches Integer to 0 atomically 50 */ 51 func (c *AtomicFlag) Clear() bool { 52 return atomic.CompareAndSwapInt32(&c.Value, 1, 0) 53 } 54 55 /* 56 Set switches Integer to 1 atomically 57 */ 58 func (c *AtomicFlag) Set() bool { 59 return atomic.CompareAndSwapInt32(&c.Value, 0, 1) 60 } 61 62 /* 63 State returns current state 64 */ 65 func (c *AtomicFlag) State() bool { 66 v := atomic.LoadInt32(&c.Value) 67 return bool(v != 0) 68 } 69 70 /* 71 AtomicSingleIndex - it's an atomic positive integer single set value 72 */ 73 type AtomicSingleIndex struct{ v uint64 } 74 75 /* 76 Get returns index value 77 */ 78 func (c *AtomicSingleIndex) Get() (int, bool) { 79 v := atomic.LoadUint64(&c.v) 80 return int(v - 1), v != 0 81 } 82 83 /* 84 Set sets value if it was not set before 85 */ 86 func (c *AtomicSingleIndex) Set(value int) (int, bool) { 87 if atomic.CompareAndSwapUint64(&c.v, 0, uint64(value)+1) { 88 return value, true 89 } 90 return int(atomic.LoadUint64(&c.v) - 1), false 91 }