/
round-robin.go
74 lines (65 loc) · 1.13 KB
/
round-robin.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
62
63
64
65
66
67
68
69
70
71
72
73
74
package rp
import (
"sync"
)
type roundRobin struct {
sync.Mutex
conns []*proxyConnection
idx int
maxWeight int
currentGCD int
currentWeight int
}
func newRoundRobin() *roundRobin {
out := &roundRobin{
conns: make([]*proxyConnection, 0),
idx: -1,
}
return out
}
func (r *roundRobin) Add(p *proxyConnection) {
if p.weight <= 0 {
panic("weight must be greater than 0")
}
if r.currentGCD == 0 {
r.currentGCD = p.weight
r.maxWeight = p.weight
} else {
r.currentGCD = gcd(r.currentGCD, p.weight)
if r.maxWeight < p.weight {
r.maxWeight = p.weight
}
}
r.conns = append(r.conns, p)
}
func (r *roundRobin) Get() *proxyConnection {
r.Lock()
defer r.Unlock()
if len(r.conns) == 1 {
return r.conns[0]
}
for {
r.idx = (r.idx + 1) % len(r.conns)
if r.idx == 0 {
r.currentWeight = r.currentWeight - r.currentGCD
if r.currentWeight <= 0 {
r.currentWeight = r.maxWeight
}
}
if r.conns[r.idx].weight >= r.currentWeight {
return r.conns[r.idx]
}
}
}
func gcd(x, y int) int {
var t int
for {
t = (x % y)
if t > 0 {
x = y
y = t
} else {
return y
}
}
}