github.com/pharosnet/flyline@v1.0.2/sequence.go (about)

     1  package flyline
     2  
     3  import (
     4  	"runtime"
     5  	"sync/atomic"
     6  	"time"
     7  )
     8  
     9  const (
    10  	padding = 7
    11  )
    12  
    13  // Sequence New Function, value starts from -1.
    14  func NewSequence() (seq *Sequence) {
    15  	seq = &Sequence{value: int64(-1)}
    16  	return
    17  }
    18  
    19  // sequence, atomic operators.
    20  type Sequence struct {
    21  	value int64
    22  	rhs   [padding]int64
    23  }
    24  
    25  // Atomic increment
    26  func (s *Sequence) Incr() (value int64) {
    27  	times := 10
    28  	for {
    29  		times--
    30  		nextValue := s.Get() + 1
    31  		ok := atomic.CompareAndSwapInt64(&s.value, s.value, nextValue)
    32  		if ok {
    33  			value = nextValue
    34  			break
    35  		}
    36  		time.Sleep(1 * time.Nanosecond)
    37  		if times <= 0 {
    38  			times = 10
    39  			runtime.Gosched()
    40  		}
    41  	}
    42  	return
    43  }
    44  
    45  // Atomic decrement
    46  func (s *Sequence) Decr() (value int64) {
    47  	times := 10
    48  	for {
    49  		times--
    50  		preValue := s.Get() - 1
    51  		ok := atomic.CompareAndSwapInt64(&s.value, s.value, preValue)
    52  		if ok {
    53  			value = preValue
    54  			break
    55  		}
    56  		time.Sleep(1 * time.Nanosecond)
    57  		if times <= 0 {
    58  			times = 10
    59  			runtime.Gosched()
    60  		}
    61  	}
    62  	return
    63  }
    64  
    65  // Atomic get Sequence value.
    66  func (s *Sequence) Get() (value int64) {
    67  	value = atomic.LoadInt64(&s.value)
    68  	return
    69  }