Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: src/core/SkTDPQueue.h

Issue 914003004: Add a templated priority queue class. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: comments Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #ifndef SkTDPQueue_DEFINED
9 #define SkTDPQueue_DEFINED
10
11 #include "SkTDArray.h"
12
13 /**
14 * This class implements a priority queue. T is the type of the elements in the queue. LESS is a
15 * function that compares two Ts and returns true if the first is higher priorit y than the second.
16 *
17 * Optionally objects may know their index into the priority queue. The queue wi ll update the index
18 * as the objects move through the queue. This is enabled by using a non-NULL fu nction for INDEX.
19 * When an INDEX function is provided random deletes from the queue are allowed using remove().
20 * Additionally, the * priority is allowed to change as long as priorityDidChang e() is called
21 * afterwards. In debug builds the index will be set to -1 before an element is removed from the
22 * queue.
23 */
24 template <typename T,
25 bool (*LESS)(const T&, const T&),
26 int* (*INDEX)(const T&) = NULL>
27 class SkTDPQueue : public SkNoncopyable {
28 public:
29 SkTDPQueue() {}
30
31 /** Number of items in the queue. */
32 int count() const { return fArray.count(); }
33
34 /** Gets the next item in the queue without popping it. */
35 const T& peek() const { return fArray[0]; }
egdaniel 2015/02/11 18:58:27 we assert the count > 0 on pop, but not here. Obvi
bsalomon 2015/02/11 19:14:51 nope, fair point. Will remove the redundant assert
36 T& peek() { return fArray[0]; }
37
38 /** Removes the next item. */
39 void pop() {
40 SkASSERT(fArray.count());
41 this->validate();
42 SkDEBUGCODE(if (INDEX) { *INDEX(fArray[0]) = -1; })
43 if (1 == fArray.count()) {
44 fArray.pop();
45 return;
46 }
47
48 fArray[0] = fArray[fArray.count() - 1];
49 this->setIndex(0);
50 fArray.pop();
51 this->percolateDownIfNecessary(0);
52
53 this->validate();
54 }
55
56 /** Inserts a new item in the queue based on its priority. */
57 void insert(T entry) {
58 this->validate();
59 int index = fArray.count();
60 *fArray.append() = entry;
61 this->setIndex(fArray.count() - 1);
62 this->percolateUpIfNecessary(index);
63 this->validate();
64 }
65
66 /** Random access removal. This requires that the INDEX function is non-NULL . */
67 void remove(T entry) {
68 SkASSERT(NULL != INDEX);
69 int index = *INDEX(entry);
70 SkASSERT(index >= 0 && index < fArray.count());
egdaniel 2015/02/11 18:58:27 should we assert the entry == fArray[index]? The o
bsalomon 2015/02/11 19:14:52 validate() does that.
71 this->validate();
72 SkDEBUGCODE(if (INDEX) { *INDEX(fArray[index]) = -1; })
egdaniel 2015/02/11 18:58:27 We don't need to checkout INDEX here, since we ass
bsalomon 2015/02/11 19:14:52 Done.
73 if (index == fArray.count() - 1) {
74 fArray.pop();
75 return;
76 }
77 fArray[index] = fArray[fArray.count() - 1];
78 fArray.pop();
79 this->setIndex(index);
80 this->percolateUpOrDown(index);
81 this->validate();
82 }
83
84 /** Notification that the priority of an entry has changed. This must be cal led after an
85 item's priority is changed to maintain correct ordering. Changing the pr iority is only
86 allowed if an INDEX function is provided. */
87 void priorityDidChange(T entry) {
88 SkASSERT(NULL != INDEX);
89 int index = *INDEX(entry);
90 SkASSERT(index >= 0 && index < fArray.count());
91 this->validate(index);
92 this->percolateUpOrDown(index);
93 this->validate();
94 }
95
96 private:
97 static int LeftOf(int x) { SkASSERT(x >= 0); return 2 * x + 1; }
98 static int ParentOf(int x) { SkASSERT(x > 0); return (x - 1) >> 1; }
99
100 void percolateUpOrDown(int index) {
101 SkASSERT(index >= 0);
102 if (!percolateUpIfNecessary(index)) {
103 this->validate(index);
104 this->percolateDownIfNecessary(index);
105 }
106 }
107
108 bool percolateUpIfNecessary(int index) {
109 SkASSERT(index >= 0);
110 bool percolated = false;
111 do {
112 if (0 == index) {
113 return false;
114 }
115 int p = ParentOf(index);
116 if (LESS(fArray[index], fArray[p])) {
117 SkTSwap(fArray[index], fArray[p]);
118 this->setIndex(index);
119 this->setIndex(p);
120 index = p;
121 percolated = true;
122 } else {
123 return percolated;
124 }
125 this->validate(index);
126 } while (true);
127 }
128
129 void percolateDownIfNecessary(int index) {
130 SkASSERT(index >= 0);
131 do {
132 int child = LeftOf(index);
133
134 if (child >= fArray.count()) {
135 // We're a leaf.
136 return;
137 }
138
139 if (child + 1 >= fArray.count()) {
140 // We only have a left child.
141 if (LESS(fArray[child], fArray[index])) {
142 SkTSwap(fArray[child], fArray[index]);
143 this->setIndex(index);
144 this->setIndex(child);
145 return;
146 }
147 } else if (LESS(fArray[child + 1], fArray[child])) {
148 // The right child is the one we should swap with, if we swap.
149 child++;
150 }
151
152 // Check if we need to swap.
153 if (LESS(fArray[child], fArray[index])) {
154 SkTSwap(fArray[child], fArray[index]);
155 this->setIndex(index);
156 this->setIndex(child);
157 index = child;
158 } else {
159 // We're less than both our children.
160 return;
161 }
162 this->validate(index);
163 } while (true);
164 }
165
166 void setIndex(int index) {
167 SkASSERT(index < fArray.count());
168 if (INDEX) {
169 *INDEX(fArray[index]) = index;
170 }
171 }
172
173 #ifdef SK_DEBUG
174 void validate(int excludedIndex = -1) const {
175 for (int i = 1; i < fArray.count(); ++i) {
176 int p = ParentOf(i);
177 if (excludedIndex != p && excludedIndex != i) {
178 SkASSERT(!(LESS(fArray[i], fArray[p])));
179 SkASSERT(!SkToBool(INDEX) || *INDEX(fArray[i]) == i);
180 }
181 }
182 }
183 #endif
184
185 SkTDArray<T> fArray;
186
187 typedef SkNoncopyable INHERITED;
188 };
189
190 #endif
OLDNEW
« no previous file with comments | « gyp/tests.gypi ('k') | tests/TDPQueueTest.cpp » ('j') | tests/TDPQueueTest.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698