/
connPool.go
92 lines (81 loc) · 1.56 KB
/
connPool.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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package tunnel
import (
log "github.com/Lafeng/deblocus/golang/glog"
"sort"
"sync"
"sync/atomic"
)
type TSPriority struct {
last int64
rank int64
}
type ConnPool struct {
pool sortableConns
lock sync.Locker
}
func NewConnPool() *ConnPool {
return &ConnPool{lock: new(sync.Mutex)}
}
type sortableConns []*Conn
func (h sortableConns) Len() int { return len(h) }
func (h sortableConns) Less(i, j int) bool { return h[i].priority.rank > h[j].priority.rank } // reverse
func (h sortableConns) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *ConnPool) Push(x *Conn) {
h.lock.Lock()
defer h.lock.Unlock()
h.pool = append(h.pool, x)
}
func (h *ConnPool) Remove(c *Conn) bool {
h.lock.Lock()
defer h.lock.Unlock()
var (
x int = -1
n = h.pool.Len()
)
for i := 0; i < n; i++ {
if h.pool[i] == c {
x = i
break
}
}
if x < 0 {
return false
}
switch {
case x == 0:
h.pool = h.pool[1:]
case x == n-1:
h.pool = h.pool[:x]
case x > 0 && x < n-1:
copy(h.pool[x:], h.pool[x+1:])
h.pool = h.pool[:n-1]
}
return true
}
func (h *ConnPool) Len() int {
h.lock.Lock()
defer h.lock.Unlock()
return h.pool.Len()
}
func (h *ConnPool) Select() *Conn {
h.lock.Lock()
defer h.lock.Unlock()
if h.pool.Len() < 1 {
return nil
}
sort.Sort(h.pool)
if log.V(5) {
log.Infoln("selected tun", h.pool[0].LocalAddr())
}
selected := h.pool[0]
atomic.AddInt64(&selected.priority.rank, -1)
return selected
}
func (h *ConnPool) destroy() {
h.lock.Lock()
defer h.lock.Unlock()
for _, c := range h.pool {
SafeClose(c)
}
h.pool = nil
}