@@ -5,44 +5,38 @@ package sync
5
5
6
6
import (
7
7
"bytes"
8
- "container/heap"
9
8
9
+ "github.com/ava-labs/avalanchego/utils/heap"
10
10
"github.com/ava-labs/avalanchego/utils/math"
11
11
"github.com/ava-labs/avalanchego/utils/maybe"
12
12
13
13
"github.com/google/btree"
14
14
)
15
15
16
- var _ heap.Interface = (* innerHeap )(nil )
17
-
18
- type heapItem struct {
19
- workItem * workItem
20
- heapIndex int
21
- }
22
-
23
- type innerHeap []* heapItem
24
-
25
16
// A priority queue of syncWorkItems.
26
17
// Note that work item ranges never overlap.
27
18
// Supports range merging and priority updating.
28
19
// Not safe for concurrent use.
29
20
type workHeap struct {
30
21
// Max heap of items by priority.
31
22
// i.e. heap.Pop returns highest priority item.
32
- innerHeap innerHeap
23
+ innerHeap heap. Set [ * workItem ]
33
24
// The heap items sorted by range start.
34
25
// A Nothing start is considered to be the smallest.
35
- sortedItems * btree.BTreeG [* heapItem ]
26
+ sortedItems * btree.BTreeG [* workItem ]
36
27
closed bool
37
28
}
38
29
39
30
func newWorkHeap () * workHeap {
40
31
return & workHeap {
32
+ innerHeap : heap.NewSet [* workItem ](func (a , b * workItem ) bool {
33
+ return a .priority > b .priority
34
+ }),
41
35
sortedItems : btree .NewG (
42
36
2 ,
43
- func (a , b * heapItem ) bool {
44
- aNothing := a .workItem . start .IsNothing ()
45
- bNothing := b .workItem . start .IsNothing ()
37
+ func (a , b * workItem ) bool {
38
+ aNothing := a .start .IsNothing ()
39
+ bNothing := b .start .IsNothing ()
46
40
if aNothing {
47
41
// [a] is Nothing, so if [b] is Nothing, they're equal.
48
42
// Otherwise, [b] is greater.
@@ -53,7 +47,7 @@ func newWorkHeap() *workHeap {
53
47
return false
54
48
}
55
49
// [a] and [b] both contain values. Compare the values.
56
- return bytes .Compare (a .workItem . start .Value (), b . workItem .start .Value ()) < 0
50
+ return bytes .Compare (a .start .Value (), b .start .Value ()) < 0
57
51
},
58
52
),
59
53
}
@@ -70,10 +64,8 @@ func (wh *workHeap) Insert(item *workItem) {
70
64
return
71
65
}
72
66
73
- wrappedItem := & heapItem {workItem : item }
74
-
75
- heap .Push (& wh .innerHeap , wrappedItem )
76
- wh .sortedItems .ReplaceOrInsert (wrappedItem )
67
+ wh .innerHeap .Push (item )
68
+ wh .sortedItems .ReplaceOrInsert (item )
77
69
}
78
70
79
71
// Pops and returns a work item from the heap.
@@ -82,9 +74,9 @@ func (wh *workHeap) GetWork() *workItem {
82
74
if wh .closed || wh .Len () == 0 {
83
75
return nil
84
76
}
85
- item := heap . Pop ( & wh .innerHeap ).( * heapItem )
77
+ item , _ := wh .innerHeap . Pop ( )
86
78
wh .sortedItems .Delete (item )
87
- return item . workItem
79
+ return item
88
80
}
89
81
90
82
// Insert the item into the heap, merging it with existing items
@@ -99,25 +91,23 @@ func (wh *workHeap) MergeInsert(item *workItem) {
99
91
return
100
92
}
101
93
102
- var mergedBefore , mergedAfter * heapItem
103
- searchItem := & heapItem {
104
- workItem : & workItem {
105
- start : item .start ,
106
- },
94
+ var mergedBefore , mergedAfter * workItem
95
+ searchItem := & workItem {
96
+ start : item .start ,
107
97
}
108
98
109
99
// Find the item with the greatest start range which is less than [item.start].
110
100
// Note that the iterator function will run at most once, since it always returns false.
111
101
wh .sortedItems .DescendLessOrEqual (
112
102
searchItem ,
113
- func (beforeItem * heapItem ) bool {
114
- if item .localRootID == beforeItem .workItem . localRootID &&
115
- maybe .Equal (item .start , beforeItem .workItem . end , bytes .Equal ) {
103
+ func (beforeItem * workItem ) bool {
104
+ if item .localRootID == beforeItem .localRootID &&
105
+ maybe .Equal (item .start , beforeItem .end , bytes .Equal ) {
116
106
// [beforeItem.start, beforeItem.end] and [item.start, item.end] are
117
107
// merged into [beforeItem.start, item.end]
118
- beforeItem .workItem . end = item .end
119
- beforeItem .workItem . priority = math .Max (item .priority , beforeItem . workItem .priority )
120
- heap . Fix ( & wh .innerHeap , beforeItem . heapIndex )
108
+ beforeItem .end = item .end
109
+ beforeItem .priority = math .Max (item .priority , beforeItem .priority )
110
+ wh .innerHeap . Fix ( beforeItem )
121
111
mergedBefore = beforeItem
122
112
}
123
113
return false
@@ -127,14 +117,14 @@ func (wh *workHeap) MergeInsert(item *workItem) {
127
117
// Note that the iterator function will run at most once, since it always returns false.
128
118
wh .sortedItems .AscendGreaterOrEqual (
129
119
searchItem ,
130
- func (afterItem * heapItem ) bool {
131
- if item .localRootID == afterItem .workItem . localRootID &&
132
- maybe .Equal (item .end , afterItem .workItem . start , bytes .Equal ) {
120
+ func (afterItem * workItem ) bool {
121
+ if item .localRootID == afterItem .localRootID &&
122
+ maybe .Equal (item .end , afterItem .start , bytes .Equal ) {
133
123
// [item.start, item.end] and [afterItem.start, afterItem.end] are merged into
134
124
// [item.start, afterItem.end].
135
- afterItem .workItem . start = item .start
136
- afterItem .workItem . priority = math .Max (item .priority , afterItem . workItem .priority )
137
- heap . Fix ( & wh .innerHeap , afterItem . heapIndex )
125
+ afterItem .start = item .start
126
+ afterItem .priority = math .Max (item .priority , afterItem .priority )
127
+ wh .innerHeap . Fix ( afterItem )
138
128
mergedAfter = afterItem
139
129
}
140
130
return false
@@ -144,12 +134,12 @@ func (wh *workHeap) MergeInsert(item *workItem) {
144
134
// we can combine the before item with the after item
145
135
if mergedBefore != nil && mergedAfter != nil {
146
136
// combine the two ranges
147
- mergedBefore .workItem . end = mergedAfter . workItem .end
137
+ mergedBefore .end = mergedAfter .end
148
138
// remove the second range since it is now covered by the first
149
139
wh .remove (mergedAfter )
150
140
// update the priority
151
- mergedBefore .workItem . priority = math .Max (mergedBefore .workItem . priority , mergedAfter . workItem .priority )
152
- heap . Fix ( & wh .innerHeap , mergedBefore . heapIndex )
141
+ mergedBefore .priority = math .Max (mergedBefore .priority , mergedAfter .priority )
142
+ wh .innerHeap . Fix ( mergedBefore )
153
143
}
154
144
155
145
// nothing was merged, so add new item to the heap
@@ -160,43 +150,11 @@ func (wh *workHeap) MergeInsert(item *workItem) {
160
150
}
161
151
162
152
// Deletes [item] from the heap.
163
- func (wh * workHeap ) remove (item * heapItem ) {
164
- heap .Remove (& wh .innerHeap , item .heapIndex )
165
-
153
+ func (wh * workHeap ) remove (item * workItem ) {
154
+ wh .innerHeap .Remove (item )
166
155
wh .sortedItems .Delete (item )
167
156
}
168
157
169
158
func (wh * workHeap ) Len () int {
170
159
return wh .innerHeap .Len ()
171
160
}
172
-
173
- // below this line are the implementations required for heap.Interface
174
-
175
- func (h innerHeap ) Len () int {
176
- return len (h )
177
- }
178
-
179
- func (h innerHeap ) Less (i int , j int ) bool {
180
- return h [i ].workItem .priority > h [j ].workItem .priority
181
- }
182
-
183
- func (h innerHeap ) Swap (i int , j int ) {
184
- h [i ], h [j ] = h [j ], h [i ]
185
- h [i ].heapIndex = i
186
- h [j ].heapIndex = j
187
- }
188
-
189
- func (h * innerHeap ) Pop () interface {} {
190
- old := * h
191
- n := len (old )
192
- item := old [n - 1 ]
193
- old [n - 1 ] = nil
194
- * h = old [0 : n - 1 ]
195
- return item
196
- }
197
-
198
- func (h * innerHeap ) Push (x interface {}) {
199
- item := x .(* heapItem )
200
- item .heapIndex = len (* h )
201
- * h = append (* h , item )
202
- }
0 commit comments