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  }