-
Notifications
You must be signed in to change notification settings - Fork 23
/
recycler.go
63 lines (56 loc) · 1.14 KB
/
recycler.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
package main
import (
"container/list"
"time"
)
type recyclerItem struct {
when time.Time
buf []byte
}
type recycler struct {
q *list.List
takeChan, giveChan chan []byte
}
func NewRecycler(size uint32) *recycler {
r := &recycler{
q: new(list.List),
takeChan: make(chan []byte),
giveChan: make(chan []byte),
}
go r.cycle(size)
return r
}
func (r *recycler) cycle(size uint32) {
for {
if r.q.Len() == 0 {
//put to front so that we always use the most recent buf
r.q.PushFront(recyclerItem{when: time.Now(), buf: make([]byte, size)})
}
i := r.q.Front()
timeout := time.NewTimer(time.Minute)
select {
case b := <-r.giveChan:
timeout.Stop()
r.q.PushFront(recyclerItem{when: time.Now(), buf: b})
case r.takeChan <- i.Value.(recyclerItem).buf:
timeout.Stop()
r.q.Remove(i)
case <-timeout.C:
i := r.q.Front()
for i != nil {
n := i.Next()
if time.Since(i.Value.(recyclerItem).when) > time.Minute {
r.q.Remove(i)
i.Value = nil
}
i = n
}
}
}
}
func (r *recycler) take() []byte {
return <-r.takeChan
}
func (r *recycler) give(b []byte) {
r.giveChan <- b
}