Skip to content

Commit 20ab5dc

Browse files
committed
Deprecate several global variables
This allows better data race protection and makes it more possible to have multi nodes running on the same program with different options. A temp global mutex was added to protect data races caused by NewNode until the deprecated variables are removed. fixed bwmarrin#15
1 parent 267d02f commit 20ab5dc

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

snowflake.go

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ var (
2424
// Remember, you have a total 22 bits to share between Node/Step
2525
StepBits uint8 = 12
2626

27+
// DEPRECATED: the below four variables will be removed in a future release.
28+
mu sync.Mutex
2729
nodeMax int64 = -1 ^ (-1 << NodeBits)
2830
nodeMask = nodeMax << StepBits
2931
stepMask int64 = -1 ^ (-1 << StepBits)
@@ -79,6 +81,12 @@ type Node struct {
7981
time int64
8082
node int64
8183
step int64
84+
85+
nodeMax int64
86+
nodeMask int64
87+
stepMask int64
88+
timeShift uint8
89+
nodeShift uint8
8290
}
8391

8492
// An ID is a custom type used for a snowflake ID. This is used so we can
@@ -90,21 +98,28 @@ type ID int64
9098
func NewNode(node int64) (*Node, error) {
9199

92100
// re-calc in case custom NodeBits or StepBits were set
101+
// DEPRECATED: the below block will be removed in a future release.
102+
mu.Lock()
93103
nodeMax = -1 ^ (-1 << NodeBits)
94104
nodeMask = nodeMax << StepBits
95105
stepMask = -1 ^ (-1 << StepBits)
96106
timeShift = NodeBits + StepBits
97107
nodeShift = StepBits
98-
99-
if node < 0 || node > nodeMax {
100-
return nil, errors.New("Node number must be between 0 and " + strconv.FormatInt(nodeMax, 10))
108+
mu.Unlock()
109+
110+
n := Node{}
111+
n.node = node
112+
n.nodeMax = -1 ^ (-1 << NodeBits)
113+
n.nodeMask = n.nodeMax << StepBits
114+
n.stepMask = -1 ^ (-1 << StepBits)
115+
n.timeShift = NodeBits + StepBits
116+
n.nodeShift = StepBits
117+
118+
if n.node < 0 || n.node > n.nodeMax {
119+
return nil, errors.New("Node number must be between 0 and " + strconv.FormatInt(n.nodeMax, 10))
101120
}
102121

103-
return &Node{
104-
time: 0,
105-
node: node,
106-
step: 0,
107-
}, nil
122+
return &n, nil
108123
}
109124

110125
// Generate creates and returns a unique snowflake ID
@@ -115,7 +130,7 @@ func (n *Node) Generate() ID {
115130
now := time.Now().UnixNano() / 1000000
116131

117132
if n.time == now {
118-
n.step = (n.step + 1) & stepMask
133+
n.step = (n.step + 1) & n.stepMask
119134

120135
if n.step == 0 {
121136
for now <= n.time {
@@ -128,8 +143,8 @@ func (n *Node) Generate() ID {
128143

129144
n.time = now
130145

131-
r := ID((now-Epoch)<<timeShift |
132-
(n.node << nodeShift) |
146+
r := ID((now-Epoch)<<n.timeShift |
147+
(n.node << n.nodeShift) |
133148
(n.step),
134149
)
135150

@@ -253,16 +268,19 @@ func (f ID) IntBytes() [8]byte {
253268
}
254269

255270
// Time returns an int64 unix timestamp of the snowflake ID time
271+
// DEPRECATED: the below function will be removed in a future release.
256272
func (f ID) Time() int64 {
257273
return (int64(f) >> timeShift) + Epoch
258274
}
259275

260276
// Node returns an int64 of the snowflake ID node number
277+
// DEPRECATED: the below function will be removed in a future release.
261278
func (f ID) Node() int64 {
262279
return int64(f) & nodeMask >> nodeShift
263280
}
264281

265282
// Step returns an int64 of the snowflake step (or sequence) number
283+
// DEPRECATED: the below function will be removed in a future release.
266284
func (f ID) Step() int64 {
267285
return int64(f) & stepMask
268286
}

0 commit comments

Comments
 (0)