Chromium Code Reviews| 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 |