-
Notifications
You must be signed in to change notification settings - Fork 1
/
iterator.go
85 lines (69 loc) · 1.42 KB
/
iterator.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
package treap
import "sync"
// Iterator contains treap iteration state. Its methods are NOT thread-safe, but
// multiple concurrent iterators are supported.
type Iterator struct {
*Node
stack *stack
}
// Iter walks the tree in key-order.
func (h Handle) Iter(n *Node) *Iterator {
it := iterPool.Get().(*Iterator)
it.stack = push(nil, n)
it.Next()
return it
}
// Next item.
func (it *Iterator) Next() {
// are we resuming?
if it.Node != nil {
it.Node = it.Node.Right
} else {
it.Node, it.stack = pop(it.stack)
}
for {
if it.Node == nil {
it.Node, it.stack = pop(it.stack)
break
}
it.stack = push(it.stack, it.Node)
it.Node = it.Node.Left
}
}
// Finish SHOULD be called when the iterator has been
// exhausted. An iterator is exhausted when 'it.Node'
// is nil.
func (it *Iterator) Finish() {
// return stack frames to the pool
for it.stack != nil {
_, it.stack = pop(it.stack)
}
iterPool.Put(it)
}
// Stack is a singly-linked list of nodes.
type stack struct {
*Node
next *stack
}
func push(s *stack, n *Node) *stack {
if n == nil {
return s
}
ss := stackPool.Get().(*stack)
ss.Node = n
ss.next = s
return ss
}
func pop(s *stack) (n *Node, tail *stack) {
if s != nil {
defer stackPool.Put(s)
n, tail = s.Node, s.next
}
return
}
var stackPool = sync.Pool{
New: func() interface{} { return &stack{} },
}
var iterPool = sync.Pool{
New: func() interface{} { return &Iterator{} },
}