-
Notifications
You must be signed in to change notification settings - Fork 0
/
seq.go
61 lines (50 loc) · 1.35 KB
/
seq.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package link
import "sync/atomic"
// Seq is a sequence number generator.
//
// All public methods can be safely called concurrently.
type Seq struct {
seq uint64
incrementBy uint64
}
func (seq *Seq) forceIncrementBy() uint64 {
if seq.incrementBy == 0 {
return 1
}
return seq.incrementBy
}
func (seq *Seq) init() {
seq.seq -= seq.forceIncrementBy()
}
// Next advances the sequence to its next value and returns that value.
func (seq *Seq) Next() uint64 {
return atomic.AddUint64(&seq.seq, seq.forceIncrementBy())
}
type SeqOption func(seq *Seq)
// SeqStartWith allows the sequence to begin anywhere. The default starting value is 0.
func SeqStartWith(startWith uint64) SeqOption {
return func(seq *Seq) {
seq.seq = startWith
}
}
// SeqIncrementBy specifies which value is added to the current sequence value to create an new value.
// A positive value will make an ascending sequence, a negative one a descending sequence.
// The default value is 1.
func SeqIncrementBy(incrementBy uint64) SeqOption {
return func(seq *Seq) {
seq.incrementBy = incrementBy
}
}
// NewSeq creates a sequence with a set of options.
func NewSeq(opts ...SeqOption) *Seq {
seq := new(Seq)
for _, opt := range opts {
opt(seq)
}
seq.init()
return seq
}
// NextChild returns the next derived child id.
func NextChild(id ID, seq *Seq) ID {
return id.Child(seq.Next())
}