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 #15
This commit is contained in:
Bruce Marriner 2019-04-10 01:33:37 +00:00
parent 267d02f8b9
commit 20ab5dc6a4

View File

@ -24,6 +24,8 @@ var (
// Remember, you have a total 22 bits to share between Node/Step // Remember, you have a total 22 bits to share between Node/Step
StepBits uint8 = 12 StepBits uint8 = 12
// DEPRECATED: the below four variables will be removed in a future release.
mu sync.Mutex
nodeMax int64 = -1 ^ (-1 << NodeBits) nodeMax int64 = -1 ^ (-1 << NodeBits)
nodeMask = nodeMax << StepBits nodeMask = nodeMax << StepBits
stepMask int64 = -1 ^ (-1 << StepBits) stepMask int64 = -1 ^ (-1 << StepBits)
@ -79,6 +81,12 @@ type Node struct {
time int64 time int64
node int64 node int64
step int64 step int64
nodeMax int64
nodeMask int64
stepMask int64
timeShift uint8
nodeShift uint8
} }
// An ID is a custom type used for a snowflake ID. This is used so we can // An ID is a custom type used for a snowflake ID. This is used so we can
@ -90,21 +98,28 @@ type ID int64
func NewNode(node int64) (*Node, error) { func NewNode(node int64) (*Node, error) {
// re-calc in case custom NodeBits or StepBits were set // re-calc in case custom NodeBits or StepBits were set
// DEPRECATED: the below block will be removed in a future release.
mu.Lock()
nodeMax = -1 ^ (-1 << NodeBits) nodeMax = -1 ^ (-1 << NodeBits)
nodeMask = nodeMax << StepBits nodeMask = nodeMax << StepBits
stepMask = -1 ^ (-1 << StepBits) stepMask = -1 ^ (-1 << StepBits)
timeShift = NodeBits + StepBits timeShift = NodeBits + StepBits
nodeShift = StepBits nodeShift = StepBits
mu.Unlock()
if node < 0 || node > nodeMax { n := Node{}
return nil, errors.New("Node number must be between 0 and " + strconv.FormatInt(nodeMax, 10)) n.node = node
n.nodeMax = -1 ^ (-1 << NodeBits)
n.nodeMask = n.nodeMax << StepBits
n.stepMask = -1 ^ (-1 << StepBits)
n.timeShift = NodeBits + StepBits
n.nodeShift = StepBits
if n.node < 0 || n.node > n.nodeMax {
return nil, errors.New("Node number must be between 0 and " + strconv.FormatInt(n.nodeMax, 10))
} }
return &Node{ return &n, nil
time: 0,
node: node,
step: 0,
}, nil
} }
// Generate creates and returns a unique snowflake ID // Generate creates and returns a unique snowflake ID
@ -115,7 +130,7 @@ func (n *Node) Generate() ID {
now := time.Now().UnixNano() / 1000000 now := time.Now().UnixNano() / 1000000
if n.time == now { if n.time == now {
n.step = (n.step + 1) & stepMask n.step = (n.step + 1) & n.stepMask
if n.step == 0 { if n.step == 0 {
for now <= n.time { for now <= n.time {
@ -128,8 +143,8 @@ func (n *Node) Generate() ID {
n.time = now n.time = now
r := ID((now-Epoch)<<timeShift | r := ID((now-Epoch)<<n.timeShift |
(n.node << nodeShift) | (n.node << n.nodeShift) |
(n.step), (n.step),
) )
@ -253,16 +268,19 @@ func (f ID) IntBytes() [8]byte {
} }
// Time returns an int64 unix timestamp of the snowflake ID time // Time returns an int64 unix timestamp of the snowflake ID time
// DEPRECATED: the below function will be removed in a future release.
func (f ID) Time() int64 { func (f ID) Time() int64 {
return (int64(f) >> timeShift) + Epoch return (int64(f) >> timeShift) + Epoch
} }
// Node returns an int64 of the snowflake ID node number // Node returns an int64 of the snowflake ID node number
// DEPRECATED: the below function will be removed in a future release.
func (f ID) Node() int64 { func (f ID) Node() int64 {
return int64(f) & nodeMask >> nodeShift return int64(f) & nodeMask >> nodeShift
} }
// Step returns an int64 of the snowflake step (or sequence) number // Step returns an int64 of the snowflake step (or sequence) number
// DEPRECATED: the below function will be removed in a future release.
func (f ID) Step() int64 { func (f ID) Step() int64 {
return int64(f) & stepMask return int64(f) & stepMask
} }