forked from nelsam/gxui
/
call_queue.go
72 lines (63 loc) · 1.02 KB
/
call_queue.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
package gl
import "sync"
type CallQueue struct {
mu sync.Mutex
onDeck chan *callNode
head *callNode
tail *callNode
}
func NewCallQueue() *CallQueue {
return &CallQueue{
onDeck: make(chan *callNode, 1),
}
}
func (c *CallQueue) Inject(call func()) {
node := &callNode{v: call}
c.mu.Lock()
defer c.mu.Unlock()
if c.head == nil {
c.head = node
c.tail = node
c.onDeck <- c.head
return
}
c.tail.next = node
c.tail = node
}
func (c *CallQueue) Pop() (func(), bool) {
select {
case node, ok := <-c.onDeck:
if !ok {
return nil, false
}
c.shift()
return node.v, true
default:
return nil, true
}
}
func (c *CallQueue) PopWhenReady() (func(), bool) {
node, ok := <-c.onDeck
if !ok {
return nil, false
}
c.shift()
return node.v, true
}
func (c *CallQueue) Close() {
close(c.onDeck)
}
func (c *CallQueue) shift() {
c.mu.Lock()
defer c.mu.Unlock()
c.head = c.head.next
if c.head == nil {
c.tail = nil
return
}
c.onDeck <- c.head
}
type callNode struct {
v func()
next *callNode
}