OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_INTRUSIVE_HEAP_H_ | |
6 #define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_INTRUSIVE_HEAP_H_ | |
7 | |
8 #include <vector> | |
9 | |
10 #include "base/logging.h" | |
11 #include "public/platform/WebCommon.h" | |
haraken
2016/10/14 13:12:26
This is unused.
alex clarke (OOO till 29th)
2016/10/14 13:55:35
It's needed for BLINK_PLATFORM_EXPORT
| |
12 | |
13 namespace blink { | |
14 namespace scheduler { | |
15 | |
16 // A standard min-heap with the following assumptions: | |
17 // 1. T has operator <= | |
18 // 2. T has method void SetHeapIndex(size_t index) | |
19 template <typename T> | |
20 class BLINK_PLATFORM_EXPORT IntrusiveHeap { | |
haraken
2016/10/14 13:12:25
You might want to add a couple of more DCHECKs (to
haraken
2016/10/14 13:12:26
I'm just curious but what's a difference between a
alex clarke (OOO till 29th)
2016/10/14 13:55:35
It's a binary heap that requires the element to st
alex clarke (OOO till 29th)
2016/10/14 14:52:38
Thanks for making that suggestion, it revealed a b
| |
21 public: | |
22 IntrusiveHeap() : nodes_(4), size_(0) {} | |
haraken
2016/10/14 13:12:25
Add a comment about why 4.
alex clarke (OOO till 29th)
2016/10/14 13:55:35
Done.
| |
23 | |
24 bool empty() const { return size_ == 0; } | |
25 | |
26 size_t size() const { return size_; } | |
27 | |
28 void clear() { | |
29 nodes_.resize(4); | |
30 size_ = 0; | |
31 } | |
32 | |
33 const T& min() const { | |
34 DCHECK_GE(size_, 1u); | |
35 return nodes_[1]; | |
36 } | |
37 | |
38 void eraseMin() { | |
Sami
2016/10/14 07:26:16
nit: EraseMin/ExtractMin/etc. (I think we should j
alex clarke (OOO till 29th)
2016/10/14 13:55:35
For containers my preference is stl style where th
| |
39 DCHECK_GE(size_, 1u); | |
40 size_t top_index = size_--; | |
41 if (!empty()) | |
42 MoveHoleDown(1u, nodes_[top_index]); | |
43 } | |
44 | |
45 T extractMin() { | |
haraken
2016/10/14 13:12:25
Can we remove eraseMin? extractMin would be enough
alex clarke (OOO till 29th)
2016/10/14 13:55:35
I had thought we'd end up using this but it didn't
| |
46 DCHECK_GE(size_, 1u); | |
47 T top = std::move(nodes_[1]); | |
48 size_t top_index = size_--; | |
49 if (!empty()) | |
50 MoveHoleDown(1u, nodes_[top_index]); | |
51 return std::move(top); | |
52 } | |
53 | |
54 void insert(T element) { | |
55 size_++; | |
56 if (size_ >= nodes_.size()) | |
57 nodes_.resize(size_ * 2); | |
58 HeapifyUp(size_, element); | |
59 } | |
60 | |
61 void eraseHeapIndex(size_t index) { | |
62 DCHECK_GE(index, 1u); | |
63 DCHECK_LE(index, size_); | |
64 size_t top_index = size_--; | |
65 if (empty() || top_index == index) | |
66 return; | |
67 if (nodes_[index] <= nodes_[top_index]) { | |
68 MoveHoleDown(index, nodes_[top_index]); | |
69 } else { | |
70 HeapifyUp(index, nodes_[top_index]); | |
71 } | |
72 } | |
73 | |
74 void replaceMin(T element) { | |
75 // Note |element| might not be a leaf node so we can't use MoveHoleDown. | |
76 HeapifyDown(1u, element); | |
77 } | |
78 | |
79 const std::vector<T>& GetNodesForTesting() const { return nodes_; } | |
80 | |
81 private: | |
82 void MoveNode(size_t from, size_t to) { | |
83 DCHECK_GE(from, 1u); | |
84 DCHECK_LE(from, size_); | |
85 DCHECK_GE(to, 1u); | |
86 DCHECK_LE(to, size_); | |
87 DCHECK_NE(from, to); | |
88 nodes_[to] = std::move(nodes_[from]); | |
89 nodes_[to].SetHeapIndex(to); | |
90 } | |
91 | |
92 void HeapifyUp(size_t pos, T& element) { | |
Sami
2016/10/14 07:26:16
nit: non-const reference maybe should be a pointer
haraken
2016/10/14 13:12:25
MoveElementUp ?
alex clarke (OOO till 29th)
2016/10/14 13:55:35
I ended up calling this MoveHoleUpAndFillWithEleme
alex clarke (OOO till 29th)
2016/10/14 13:55:35
It should probably be an R value, since that bette
| |
93 DCHECK_GE(pos, 1u); | |
94 DCHECK_LE(pos, size_); | |
95 while (pos >= 2u) { | |
96 size_t parent_pos = pos / 2; | |
97 if (nodes_[parent_pos] <= element) | |
98 break; | |
99 | |
100 MoveNode(parent_pos, pos); | |
101 pos = parent_pos; | |
102 } | |
103 nodes_[pos] = std::move(element); | |
104 nodes_[pos].SetHeapIndex(pos); | |
105 } | |
106 | |
107 void HeapifyDown(size_t pos, T& element) { | |
haraken
2016/10/14 13:12:26
MoveElementDown ?
alex clarke (OOO till 29th)
2016/10/14 13:55:35
I ended up calling this MoveHoleDownAndFillWithEle
| |
108 DCHECK_GE(pos, 1u); | |
109 DCHECK_LE(pos, size_); | |
110 size_t child_pos = pos * 2; | |
111 while (child_pos < size_) { | |
112 if (nodes_[child_pos + 1] <= nodes_[child_pos]) | |
113 child_pos++; | |
114 | |
115 if (element <= nodes_[child_pos]) | |
116 break; | |
117 | |
118 MoveNode(child_pos, pos); | |
119 pos = child_pos; | |
120 child_pos *= 2; | |
121 } | |
122 if (child_pos == size_ && !(element <= nodes_[child_pos])) { | |
123 MoveNode(child_pos, pos); | |
124 pos = child_pos; | |
125 } | |
126 nodes_[pos] = std::move(element); | |
127 nodes_[pos].SetHeapIndex(pos); | |
128 } | |
129 | |
130 // NB this is a standard optimization, as used by the STL. HeapifyDown does | |
haraken
2016/10/14 13:12:25
NB => Note ?
BTW, we normally don't write "Note"
alex clarke (OOO till 29th)
2016/10/14 13:55:35
Done.
| |
131 // two comparisons per level, but this only does one. | |
132 // NOTE |element| is assumed to be a leaf node. | |
133 void MoveHoleDown(size_t hole, T& element) { | |
134 size_t new_hole = hole * 2; | |
135 while (new_hole <= size_) { | |
136 size_t second_child = new_hole + 1; | |
137 if (second_child <= size_ && nodes_[second_child] <= nodes_[new_hole]) | |
138 new_hole = second_child; | |
139 MoveNode(new_hole, hole); | |
140 hole = new_hole; | |
141 new_hole *= 2; | |
142 } | |
143 HeapifyUp(hole, element); | |
144 } | |
145 | |
146 std::vector<T> nodes_; // NOTE we use 1-based indexing | |
147 size_t size_; | |
148 }; | |
149 | |
150 } // namespace scheduler | |
151 } // namespace blink | |
152 | |
153 #endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_BASE_INTRUSIVE_HEAP_H_ | |
OLD | NEW |