-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathidpool.go
More file actions
87 lines (79 loc) · 1.42 KB
/
Copy pathidpool.go
File metadata and controls
87 lines (79 loc) · 1.42 KB
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package GoCryptoTCP
import (
"errors"
"math/rand"
"sync"
"time"
)
type IDPool struct {
mux sync.Mutex
pool []int
usingMap map[int]bool
cap int
available int
assignI int
using int
recycled int
}
func NewIDPool(n int) *IDPool {
p := &IDPool{
cap: n,
mux: sync.Mutex{},
pool: make([]int, n),
usingMap: make(map[int]bool, n),
using: 0,
available: n,
assignI: 0,
recycled: 0,
}
p.initPool()
return p
}
func (p *IDPool) initPool() {
for i := 0; i < p.cap; i++ {
p.pool[i] = i
}
p.shufflePool(p.cap)
}
func (p *IDPool) shufflePool(length int) {
rand.Seed(time.Now().UnixNano())
rand.Shuffle(length, func(i, j int) {
p.pool[i], p.pool[j] = p.pool[j], p.pool[i]
})
}
func (p *IDPool) Assign() (int, error) {
if p.available == 0 {
if p.recycled == 0 {
return -1, errors.New("no available id to assign")
}
p.collate()
}
p.mux.Lock()
newID := p.pool[p.assignI]
p.usingMap[newID] = true
p.available--
p.assignI++
p.using++
p.mux.Unlock()
return newID, nil
}
func (p *IDPool) collate() {
p.mux.Lock()
for i, j := 0, 0; i < p.cap; i++ {
b, ok := p.usingMap[i]
if !ok || !b {
p.pool[j] = i
j++
}
}
p.available, p.assignI, p.recycled = p.available+p.recycled, 0, 0
p.shufflePool(p.available)
p.mux.Unlock()
}
func (p *IDPool) Recycle(oldId int) {
p.mux.Lock()
p.usingMap[oldId] = false
p.recycled++
p.using--
p.mux.Unlock()
}