xref: /aosp_15_r20/external/cronet/base/containers/intrusive_heap.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2019 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_CONTAINERS_INTRUSIVE_HEAP_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_CONTAINERS_INTRUSIVE_HEAP_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker // Implements a standard max-heap, but with arbitrary element removal. To
9*6777b538SAndroid Build Coastguard Worker // facilitate this, each element has associated with it a HeapHandle (an opaque
10*6777b538SAndroid Build Coastguard Worker // wrapper around the index at which the element is stored), which is maintained
11*6777b538SAndroid Build Coastguard Worker // by the heap as elements move within it.
12*6777b538SAndroid Build Coastguard Worker //
13*6777b538SAndroid Build Coastguard Worker // An IntrusiveHeap is implemented as a standard max-heap over a std::vector<T>,
14*6777b538SAndroid Build Coastguard Worker // like std::make_heap. Insertion, removal and updating are amortized O(lg size)
15*6777b538SAndroid Build Coastguard Worker // (occasional O(size) cost if a new vector allocation is required). Retrieving
16*6777b538SAndroid Build Coastguard Worker // an element by handle is O(1). Looking up the top element is O(1). Insertions,
17*6777b538SAndroid Build Coastguard Worker // removals and updates invalidate all iterators, but handles remain valid.
18*6777b538SAndroid Build Coastguard Worker // Similar to a std::set, all iterators are read-only so as to disallow changing
19*6777b538SAndroid Build Coastguard Worker // elements and violating the heap property. That being said, if the type you
20*6777b538SAndroid Build Coastguard Worker // are storing is able to have its sort key be changed externally you can
21*6777b538SAndroid Build Coastguard Worker // repair the heap by resorting the modified element via a call to "Update".
22*6777b538SAndroid Build Coastguard Worker //
23*6777b538SAndroid Build Coastguard Worker // Example usage:
24*6777b538SAndroid Build Coastguard Worker //
25*6777b538SAndroid Build Coastguard Worker //   // Create a heap, wrapping integer elements with WithHeapHandle in order to
26*6777b538SAndroid Build Coastguard Worker //   // endow them with heap handles.
27*6777b538SAndroid Build Coastguard Worker //   IntrusiveHeap<WithHeapHandle<int>> heap;
28*6777b538SAndroid Build Coastguard Worker //
29*6777b538SAndroid Build Coastguard Worker //   // WithHeapHandle<T> is for simple or opaque types. In cases where you
30*6777b538SAndroid Build Coastguard Worker //   // control the type declaration you can also provide HeapHandle storage by
31*6777b538SAndroid Build Coastguard Worker //   // deriving from InternalHeapHandleStorage.
32*6777b538SAndroid Build Coastguard Worker //   class Foo : public InternalHeapHandleStorage {
33*6777b538SAndroid Build Coastguard Worker //    public:
34*6777b538SAndroid Build Coastguard Worker //     explicit Foo(int);
35*6777b538SAndroid Build Coastguard Worker //     ...
36*6777b538SAndroid Build Coastguard Worker //   };
37*6777b538SAndroid Build Coastguard Worker //   IntrusiveHeap<Foo> heap2;
38*6777b538SAndroid Build Coastguard Worker //
39*6777b538SAndroid Build Coastguard Worker //   // Insert some elements. Like most containers, "insert" returns an iterator
40*6777b538SAndroid Build Coastguard Worker //   // to the element in the container.
41*6777b538SAndroid Build Coastguard Worker //   heap.insert(3);
42*6777b538SAndroid Build Coastguard Worker //   heap.insert(1);
43*6777b538SAndroid Build Coastguard Worker //   auto it = heap.insert(4);
44*6777b538SAndroid Build Coastguard Worker //
45*6777b538SAndroid Build Coastguard Worker //   // By default this is a max heap, so the top element should be 4 at this
46*6777b538SAndroid Build Coastguard Worker //   // point.
47*6777b538SAndroid Build Coastguard Worker //   EXPECT_EQ(4, heap.top().value());
48*6777b538SAndroid Build Coastguard Worker //
49*6777b538SAndroid Build Coastguard Worker //   // Iterators are invalidated by further heap operations, but handles are
50*6777b538SAndroid Build Coastguard Worker //   // not. Grab a handle to the current top element so we can track it across
51*6777b538SAndroid Build Coastguard Worker //   // changes.
52*6777b538SAndroid Build Coastguard Worker //   HeapHandle* handle = it->handle();
53*6777b538SAndroid Build Coastguard Worker //
54*6777b538SAndroid Build Coastguard Worker //   // Insert a new max element. 4 should no longer be the top.
55*6777b538SAndroid Build Coastguard Worker //   heap.insert(5);
56*6777b538SAndroid Build Coastguard Worker //   EXPECT_EQ(5, heap.top().value());
57*6777b538SAndroid Build Coastguard Worker //
58*6777b538SAndroid Build Coastguard Worker //   // We can lookup and erase element 4 by its handle, even though it has
59*6777b538SAndroid Build Coastguard Worker //   // moved. Note that erasing the element invalidates the handle to it.
60*6777b538SAndroid Build Coastguard Worker //   EXPECT_EQ(4, heap.at(*handle).value());
61*6777b538SAndroid Build Coastguard Worker //   heap.erase(*handle);
62*6777b538SAndroid Build Coastguard Worker //   handle = nullptr;
63*6777b538SAndroid Build Coastguard Worker //
64*6777b538SAndroid Build Coastguard Worker //   // Popping the current max (5), makes 3 the new max, as we already erased
65*6777b538SAndroid Build Coastguard Worker //   // element 4.
66*6777b538SAndroid Build Coastguard Worker //   heap.pop();
67*6777b538SAndroid Build Coastguard Worker //   EXPECT_EQ(3, heap.top().value());
68*6777b538SAndroid Build Coastguard Worker //
69*6777b538SAndroid Build Coastguard Worker // Under the hood the HeapHandle is managed by an object implementing the
70*6777b538SAndroid Build Coastguard Worker // HeapHandleAccess interface, which is passed as a parameter to the
71*6777b538SAndroid Build Coastguard Worker // IntrusiveHeap template:
72*6777b538SAndroid Build Coastguard Worker //
73*6777b538SAndroid Build Coastguard Worker //   // Gets the heap handle associated with the element. This should return the
74*6777b538SAndroid Build Coastguard Worker //   // most recently set handle value, or HeapHandle::Invalid(). This is only
75*6777b538SAndroid Build Coastguard Worker //   // called in DCHECK builds.
76*6777b538SAndroid Build Coastguard Worker //   HeapHandle GetHeapHandle(const T*);
77*6777b538SAndroid Build Coastguard Worker //
78*6777b538SAndroid Build Coastguard Worker //   // Changes the result of GetHeapHandle. GetHeapHandle() must return the
79*6777b538SAndroid Build Coastguard Worker //   // most recent value provided to SetHeapHandle() or HeapHandle::Invalid().
80*6777b538SAndroid Build Coastguard Worker //   // In some implementations, where GetHeapHandle() can independently
81*6777b538SAndroid Build Coastguard Worker //   // reproduce the correct value, it is possible that SetHeapHandle() does
82*6777b538SAndroid Build Coastguard Worker //   // nothing.
83*6777b538SAndroid Build Coastguard Worker //   void SetHeapHandle(T*, HeapHandle);
84*6777b538SAndroid Build Coastguard Worker //
85*6777b538SAndroid Build Coastguard Worker //   // Clears the heap handle associated with the given element. After calling
86*6777b538SAndroid Build Coastguard Worker //   // this GetHeapHandle() must return HeapHandle::Invalid().
87*6777b538SAndroid Build Coastguard Worker //   void ClearHeapHandle(T*);
88*6777b538SAndroid Build Coastguard Worker //
89*6777b538SAndroid Build Coastguard Worker // The default implementation of HeapHandleAccess assumes that your type
90*6777b538SAndroid Build Coastguard Worker // provides HeapHandle storage and will simply forward these calls to equivalent
91*6777b538SAndroid Build Coastguard Worker // member functions on the type T:
92*6777b538SAndroid Build Coastguard Worker //
93*6777b538SAndroid Build Coastguard Worker //   void T::SetHeapHandle(HeapHandle)
94*6777b538SAndroid Build Coastguard Worker //   void T::ClearHeapHandle()
95*6777b538SAndroid Build Coastguard Worker //   HeapHandle T::GetHeapHandle() const
96*6777b538SAndroid Build Coastguard Worker //
97*6777b538SAndroid Build Coastguard Worker // The WithHeapHandle and InternalHeapHandleStorage classes in turn provide
98*6777b538SAndroid Build Coastguard Worker // implementations of that contract.
99*6777b538SAndroid Build Coastguard Worker //
100*6777b538SAndroid Build Coastguard Worker // In summary, to provide heap handle support for your type, you can do one of
101*6777b538SAndroid Build Coastguard Worker // the following (from most manual / least magical, to least manual / most
102*6777b538SAndroid Build Coastguard Worker // magical):
103*6777b538SAndroid Build Coastguard Worker //
104*6777b538SAndroid Build Coastguard Worker // 0. use a custom HeapHandleAccessor, and implement storage however you want;
105*6777b538SAndroid Build Coastguard Worker // 1. use the default HeapHandleAccessor, and manually provide storage on your
106*6777b538SAndroid Build Coastguard Worker //    your element type and implement the IntrusiveHeap contract;
107*6777b538SAndroid Build Coastguard Worker // 2. use the default HeapHandleAccessor, and endow your type with handle
108*6777b538SAndroid Build Coastguard Worker //    storage by deriving from a helper class (see InternalHeapHandleStorage);
109*6777b538SAndroid Build Coastguard Worker //    or,
110*6777b538SAndroid Build Coastguard Worker // 3. use the default HeapHandleAccessor, and wrap your type in a container that
111*6777b538SAndroid Build Coastguard Worker //    provides handle storage (see WithHeapHandle<T>).
112*6777b538SAndroid Build Coastguard Worker //
113*6777b538SAndroid Build Coastguard Worker // Approach 0 is suitable for custom types that already implement something akin
114*6777b538SAndroid Build Coastguard Worker // to heap handles, via back pointers or any other mechanism, but where the
115*6777b538SAndroid Build Coastguard Worker // storage is external to the objects in the heap. If you already have the
116*6777b538SAndroid Build Coastguard Worker // ability to determine where in a container an object lives despite it
117*6777b538SAndroid Build Coastguard Worker // being moved, then you don't need the overhead of storing an actual HeapHandle
118*6777b538SAndroid Build Coastguard Worker // whose value can be inferred.
119*6777b538SAndroid Build Coastguard Worker //
120*6777b538SAndroid Build Coastguard Worker // Approach 1 is is suitable in cases like the above, but where the data
121*6777b538SAndroid Build Coastguard Worker // allowing you to determine the index of an element in a container is stored
122*6777b538SAndroid Build Coastguard Worker // directly in the object itself.
123*6777b538SAndroid Build Coastguard Worker //
124*6777b538SAndroid Build Coastguard Worker // Approach 2 is suitable for types whose declarations you control, where you
125*6777b538SAndroid Build Coastguard Worker // are able to use inheritance.
126*6777b538SAndroid Build Coastguard Worker //
127*6777b538SAndroid Build Coastguard Worker // Finally, approach 3 is suitable when you are storing PODs, or a type whose
128*6777b538SAndroid Build Coastguard Worker // declaration you can not change.
129*6777b538SAndroid Build Coastguard Worker //
130*6777b538SAndroid Build Coastguard Worker // Most users should be using approach 2 or 3.
131*6777b538SAndroid Build Coastguard Worker 
132*6777b538SAndroid Build Coastguard Worker #include <algorithm>
133*6777b538SAndroid Build Coastguard Worker #include <compare>
134*6777b538SAndroid Build Coastguard Worker #include <functional>
135*6777b538SAndroid Build Coastguard Worker #include <limits>
136*6777b538SAndroid Build Coastguard Worker #include <memory>
137*6777b538SAndroid Build Coastguard Worker #include <type_traits>
138*6777b538SAndroid Build Coastguard Worker #include <utility>
139*6777b538SAndroid Build Coastguard Worker #include <vector>
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
142*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
143*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
144*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
145*6777b538SAndroid Build Coastguard Worker #include "base/ranges/algorithm.h"
146*6777b538SAndroid Build Coastguard Worker #include "third_party/abseil-cpp/absl/container/inlined_vector.h"
147*6777b538SAndroid Build Coastguard Worker 
148*6777b538SAndroid Build Coastguard Worker namespace base {
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker // Intended as a wrapper around an |index_| in the vector storage backing an
151*6777b538SAndroid Build Coastguard Worker // IntrusiveHeap. A HeapHandle is associated with each element in an
152*6777b538SAndroid Build Coastguard Worker // IntrusiveHeap, and is maintained by the heap as the object moves around
153*6777b538SAndroid Build Coastguard Worker // within it. It can be used to subsequently remove the element, or update it
154*6777b538SAndroid Build Coastguard Worker // in place.
155*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT HeapHandle {
156*6777b538SAndroid Build Coastguard Worker  public:
157*6777b538SAndroid Build Coastguard Worker   enum : size_t { kInvalidIndex = std::numeric_limits<size_t>::max() };
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker   constexpr HeapHandle() = default;
160*6777b538SAndroid Build Coastguard Worker   constexpr HeapHandle(const HeapHandle& other) = default;
HeapHandle(HeapHandle && other)161*6777b538SAndroid Build Coastguard Worker   HeapHandle(HeapHandle&& other) noexcept
162*6777b538SAndroid Build Coastguard Worker       : index_(std::exchange(other.index_, kInvalidIndex)) {}
163*6777b538SAndroid Build Coastguard Worker   ~HeapHandle() = default;
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker   HeapHandle& operator=(const HeapHandle& other) = default;
166*6777b538SAndroid Build Coastguard Worker   HeapHandle& operator=(HeapHandle&& other) noexcept {
167*6777b538SAndroid Build Coastguard Worker     index_ = std::exchange(other.index_, kInvalidIndex);
168*6777b538SAndroid Build Coastguard Worker     return *this;
169*6777b538SAndroid Build Coastguard Worker   }
170*6777b538SAndroid Build Coastguard Worker 
171*6777b538SAndroid Build Coastguard Worker   static HeapHandle Invalid();
172*6777b538SAndroid Build Coastguard Worker 
173*6777b538SAndroid Build Coastguard Worker   // Resets this handle back to an invalid state.
reset()174*6777b538SAndroid Build Coastguard Worker   void reset() { index_ = kInvalidIndex; }
175*6777b538SAndroid Build Coastguard Worker 
176*6777b538SAndroid Build Coastguard Worker   // Accessors.
index()177*6777b538SAndroid Build Coastguard Worker   size_t index() const { return index_; }
IsValid()178*6777b538SAndroid Build Coastguard Worker   bool IsValid() const { return index_ != kInvalidIndex; }
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker   // Comparison operators.
181*6777b538SAndroid Build Coastguard Worker   friend bool operator==(const HeapHandle& lhs,
182*6777b538SAndroid Build Coastguard Worker                          const HeapHandle& rhs) = default;
183*6777b538SAndroid Build Coastguard Worker   friend std::strong_ordering operator<=>(const HeapHandle& lhs,
184*6777b538SAndroid Build Coastguard Worker                                           const HeapHandle& rhs) = default;
185*6777b538SAndroid Build Coastguard Worker 
186*6777b538SAndroid Build Coastguard Worker  private:
187*6777b538SAndroid Build Coastguard Worker   template <typename T, typename Compare, typename HeapHandleAccessor>
188*6777b538SAndroid Build Coastguard Worker   friend class IntrusiveHeap;
189*6777b538SAndroid Build Coastguard Worker 
190*6777b538SAndroid Build Coastguard Worker   // Only IntrusiveHeaps can create valid HeapHandles.
HeapHandle(size_t index)191*6777b538SAndroid Build Coastguard Worker   explicit HeapHandle(size_t index) : index_(index) {}
192*6777b538SAndroid Build Coastguard Worker 
193*6777b538SAndroid Build Coastguard Worker   size_t index_ = kInvalidIndex;
194*6777b538SAndroid Build Coastguard Worker };
195*6777b538SAndroid Build Coastguard Worker 
196*6777b538SAndroid Build Coastguard Worker // The default HeapHandleAccessor, which simply forwards calls to the underlying
197*6777b538SAndroid Build Coastguard Worker // type.
198*6777b538SAndroid Build Coastguard Worker template <typename T>
199*6777b538SAndroid Build Coastguard Worker struct DefaultHeapHandleAccessor {
SetHeapHandleDefaultHeapHandleAccessor200*6777b538SAndroid Build Coastguard Worker   void SetHeapHandle(T* element, HeapHandle handle) const {
201*6777b538SAndroid Build Coastguard Worker     element->SetHeapHandle(handle);
202*6777b538SAndroid Build Coastguard Worker   }
203*6777b538SAndroid Build Coastguard Worker 
ClearHeapHandleDefaultHeapHandleAccessor204*6777b538SAndroid Build Coastguard Worker   void ClearHeapHandle(T* element) const { element->ClearHeapHandle(); }
205*6777b538SAndroid Build Coastguard Worker 
GetHeapHandleDefaultHeapHandleAccessor206*6777b538SAndroid Build Coastguard Worker   HeapHandle GetHeapHandle(const T* element) const {
207*6777b538SAndroid Build Coastguard Worker     return element->GetHeapHandle();
208*6777b538SAndroid Build Coastguard Worker   }
209*6777b538SAndroid Build Coastguard Worker };
210*6777b538SAndroid Build Coastguard Worker 
211*6777b538SAndroid Build Coastguard Worker // Intrusive heap class. This is something like a std::vector (insertion and
212*6777b538SAndroid Build Coastguard Worker // removal are similar, objects don't have a fixed address in memory) crossed
213*6777b538SAndroid Build Coastguard Worker // with a std::set (elements are considered immutable once they're in the
214*6777b538SAndroid Build Coastguard Worker // container).
215*6777b538SAndroid Build Coastguard Worker template <typename T,
216*6777b538SAndroid Build Coastguard Worker           typename Compare = std::less<T>,
217*6777b538SAndroid Build Coastguard Worker           typename HeapHandleAccessor = DefaultHeapHandleAccessor<T>>
218*6777b538SAndroid Build Coastguard Worker class IntrusiveHeap {
219*6777b538SAndroid Build Coastguard Worker  private:
220*6777b538SAndroid Build Coastguard Worker   using UnderlyingType = std::vector<T>;
221*6777b538SAndroid Build Coastguard Worker 
222*6777b538SAndroid Build Coastguard Worker  public:
223*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
224*6777b538SAndroid Build Coastguard Worker   // Types.
225*6777b538SAndroid Build Coastguard Worker 
226*6777b538SAndroid Build Coastguard Worker   using value_type = typename UnderlyingType::value_type;
227*6777b538SAndroid Build Coastguard Worker   using size_type = typename UnderlyingType::size_type;
228*6777b538SAndroid Build Coastguard Worker   using difference_type = typename UnderlyingType::difference_type;
229*6777b538SAndroid Build Coastguard Worker   using value_compare = Compare;
230*6777b538SAndroid Build Coastguard Worker   using heap_handle_accessor = HeapHandleAccessor;
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker   using reference = typename UnderlyingType::reference;
233*6777b538SAndroid Build Coastguard Worker   using const_reference = typename UnderlyingType::const_reference;
234*6777b538SAndroid Build Coastguard Worker   using pointer = typename UnderlyingType::pointer;
235*6777b538SAndroid Build Coastguard Worker   using const_pointer = typename UnderlyingType::const_pointer;
236*6777b538SAndroid Build Coastguard Worker 
237*6777b538SAndroid Build Coastguard Worker   // Iterators are read-only.
238*6777b538SAndroid Build Coastguard Worker   using iterator = typename UnderlyingType::const_iterator;
239*6777b538SAndroid Build Coastguard Worker   using const_iterator = typename UnderlyingType::const_iterator;
240*6777b538SAndroid Build Coastguard Worker   using reverse_iterator = typename UnderlyingType::const_reverse_iterator;
241*6777b538SAndroid Build Coastguard Worker   using const_reverse_iterator =
242*6777b538SAndroid Build Coastguard Worker       typename UnderlyingType::const_reverse_iterator;
243*6777b538SAndroid Build Coastguard Worker 
244*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
245*6777b538SAndroid Build Coastguard Worker   // Lifetime.
246*6777b538SAndroid Build Coastguard Worker 
247*6777b538SAndroid Build Coastguard Worker   IntrusiveHeap() = default;
IntrusiveHeap(const value_compare & comp,const heap_handle_accessor & access)248*6777b538SAndroid Build Coastguard Worker   IntrusiveHeap(const value_compare& comp, const heap_handle_accessor& access)
249*6777b538SAndroid Build Coastguard Worker       : impl_(comp, access) {}
250*6777b538SAndroid Build Coastguard Worker 
251*6777b538SAndroid Build Coastguard Worker   template <class InputIterator>
252*6777b538SAndroid Build Coastguard Worker   IntrusiveHeap(InputIterator first,
253*6777b538SAndroid Build Coastguard Worker                 InputIterator last,
254*6777b538SAndroid Build Coastguard Worker                 const value_compare& comp = value_compare(),
255*6777b538SAndroid Build Coastguard Worker                 const heap_handle_accessor& access = heap_handle_accessor())
impl_(comp,access)256*6777b538SAndroid Build Coastguard Worker       : impl_(comp, access) {
257*6777b538SAndroid Build Coastguard Worker     insert(first, last);
258*6777b538SAndroid Build Coastguard Worker   }
259*6777b538SAndroid Build Coastguard Worker 
260*6777b538SAndroid Build Coastguard Worker   // Moves an intrusive heap. The outstanding handles remain valid and end up
261*6777b538SAndroid Build Coastguard Worker   // pointing to the new heap.
262*6777b538SAndroid Build Coastguard Worker   IntrusiveHeap(IntrusiveHeap&& other) = default;
263*6777b538SAndroid Build Coastguard Worker 
264*6777b538SAndroid Build Coastguard Worker   // Copy constructor for an intrusive heap.
265*6777b538SAndroid Build Coastguard Worker   IntrusiveHeap(const IntrusiveHeap&);
266*6777b538SAndroid Build Coastguard Worker 
267*6777b538SAndroid Build Coastguard Worker   // Initializer list constructor.
268*6777b538SAndroid Build Coastguard Worker   template <typename U>
269*6777b538SAndroid Build Coastguard Worker   IntrusiveHeap(std::initializer_list<U> ilist,
270*6777b538SAndroid Build Coastguard Worker                 const value_compare& comp = value_compare(),
271*6777b538SAndroid Build Coastguard Worker                 const heap_handle_accessor& access = heap_handle_accessor())
impl_(comp,access)272*6777b538SAndroid Build Coastguard Worker       : impl_(comp, access) {
273*6777b538SAndroid Build Coastguard Worker     insert(std::begin(ilist), std::end(ilist));
274*6777b538SAndroid Build Coastguard Worker   }
275*6777b538SAndroid Build Coastguard Worker 
276*6777b538SAndroid Build Coastguard Worker   ~IntrusiveHeap();
277*6777b538SAndroid Build Coastguard Worker 
278*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
279*6777b538SAndroid Build Coastguard Worker   // Assignment.
280*6777b538SAndroid Build Coastguard Worker 
281*6777b538SAndroid Build Coastguard Worker   IntrusiveHeap& operator=(IntrusiveHeap&&) noexcept;
282*6777b538SAndroid Build Coastguard Worker   IntrusiveHeap& operator=(const IntrusiveHeap&);
283*6777b538SAndroid Build Coastguard Worker   IntrusiveHeap& operator=(std::initializer_list<value_type> ilist);
284*6777b538SAndroid Build Coastguard Worker 
285*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
286*6777b538SAndroid Build Coastguard Worker   // Element access.
287*6777b538SAndroid Build Coastguard Worker   //
288*6777b538SAndroid Build Coastguard Worker   // These provide O(1) const access to the elements in the heap. If you wish to
289*6777b538SAndroid Build Coastguard Worker   // modify an element in the heap you should first remove it from the heap, and
290*6777b538SAndroid Build Coastguard Worker   // then reinsert it into the heap, or use the "Replace*" helper functions. In
291*6777b538SAndroid Build Coastguard Worker   // the rare case where you directly modify an element in the heap you can
292*6777b538SAndroid Build Coastguard Worker   // subsequently repair the heap with "Update".
293*6777b538SAndroid Build Coastguard Worker 
at(size_type pos)294*6777b538SAndroid Build Coastguard Worker   const_reference at(size_type pos) const { return impl_.heap_.at(pos); }
at(HeapHandle pos)295*6777b538SAndroid Build Coastguard Worker   const_reference at(HeapHandle pos) const {
296*6777b538SAndroid Build Coastguard Worker     return impl_.heap_.at(pos.index());
297*6777b538SAndroid Build Coastguard Worker   }
298*6777b538SAndroid Build Coastguard Worker   const_reference operator[](size_type pos) const { return impl_.heap_[pos]; }
299*6777b538SAndroid Build Coastguard Worker   const_reference operator[](HeapHandle pos) const {
300*6777b538SAndroid Build Coastguard Worker     return impl_.heap_[pos.index()];
301*6777b538SAndroid Build Coastguard Worker   }
front()302*6777b538SAndroid Build Coastguard Worker   const_reference front() const { return impl_.heap_.front(); }
back()303*6777b538SAndroid Build Coastguard Worker   const_reference back() const { return impl_.heap_.back(); }
top()304*6777b538SAndroid Build Coastguard Worker   const_reference top() const { return impl_.heap_.front(); }
305*6777b538SAndroid Build Coastguard Worker 
306*6777b538SAndroid Build Coastguard Worker   // May or may not return a null pointer if size() is zero.
data()307*6777b538SAndroid Build Coastguard Worker   const_pointer data() const { return impl_.heap_.data(); }
308*6777b538SAndroid Build Coastguard Worker 
309*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
310*6777b538SAndroid Build Coastguard Worker   // Memory management.
311*6777b538SAndroid Build Coastguard Worker 
reserve(size_type new_capacity)312*6777b538SAndroid Build Coastguard Worker   void reserve(size_type new_capacity) { impl_.heap_.reserve(new_capacity); }
capacity()313*6777b538SAndroid Build Coastguard Worker   size_type capacity() const { return impl_.heap_.capacity(); }
shrink_to_fit()314*6777b538SAndroid Build Coastguard Worker   void shrink_to_fit() { impl_.heap_.shrink_to_fit(); }
315*6777b538SAndroid Build Coastguard Worker 
316*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
317*6777b538SAndroid Build Coastguard Worker   // Size management.
318*6777b538SAndroid Build Coastguard Worker 
319*6777b538SAndroid Build Coastguard Worker   void clear();
size()320*6777b538SAndroid Build Coastguard Worker   size_type size() const { return impl_.heap_.size(); }
max_size()321*6777b538SAndroid Build Coastguard Worker   size_type max_size() const { return impl_.heap_.max_size(); }
empty()322*6777b538SAndroid Build Coastguard Worker   bool empty() const { return impl_.heap_.empty(); }
323*6777b538SAndroid Build Coastguard Worker 
324*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
325*6777b538SAndroid Build Coastguard Worker   // Iterators.
326*6777b538SAndroid Build Coastguard Worker   //
327*6777b538SAndroid Build Coastguard Worker   // Only constant iterators are allowed.
328*6777b538SAndroid Build Coastguard Worker 
begin()329*6777b538SAndroid Build Coastguard Worker   const_iterator begin() const { return impl_.heap_.cbegin(); }
cbegin()330*6777b538SAndroid Build Coastguard Worker   const_iterator cbegin() const { return impl_.heap_.cbegin(); }
331*6777b538SAndroid Build Coastguard Worker 
end()332*6777b538SAndroid Build Coastguard Worker   const_iterator end() const { return impl_.heap_.cend(); }
cend()333*6777b538SAndroid Build Coastguard Worker   const_iterator cend() const { return impl_.heap_.cend(); }
334*6777b538SAndroid Build Coastguard Worker 
rbegin()335*6777b538SAndroid Build Coastguard Worker   const_reverse_iterator rbegin() const { return impl_.heap_.crbegin(); }
crbegin()336*6777b538SAndroid Build Coastguard Worker   const_reverse_iterator crbegin() const { return impl_.heap_.crbegin(); }
337*6777b538SAndroid Build Coastguard Worker 
rend()338*6777b538SAndroid Build Coastguard Worker   const_reverse_iterator rend() const { return impl_.heap_.crend(); }
crend()339*6777b538SAndroid Build Coastguard Worker   const_reverse_iterator crend() const { return impl_.heap_.crend(); }
340*6777b538SAndroid Build Coastguard Worker 
341*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
342*6777b538SAndroid Build Coastguard Worker   // Insertion (these are std::multiset like, with no position hints).
343*6777b538SAndroid Build Coastguard Worker   //
344*6777b538SAndroid Build Coastguard Worker   // All insertion operations invalidate iterators, pointers and references.
345*6777b538SAndroid Build Coastguard Worker   // Handles remain valid. Insertion of one element is amortized O(lg size)
346*6777b538SAndroid Build Coastguard Worker   // (occasional O(size) cost if a new vector allocation is required).
347*6777b538SAndroid Build Coastguard Worker 
insert(const value_type & value)348*6777b538SAndroid Build Coastguard Worker   const_iterator insert(const value_type& value) { return InsertImpl(value); }
insert(value_type && value)349*6777b538SAndroid Build Coastguard Worker   const_iterator insert(value_type&& value) {
350*6777b538SAndroid Build Coastguard Worker     return InsertImpl(std::move_if_noexcept(value));
351*6777b538SAndroid Build Coastguard Worker   }
352*6777b538SAndroid Build Coastguard Worker 
353*6777b538SAndroid Build Coastguard Worker   template <class InputIterator>
354*6777b538SAndroid Build Coastguard Worker   void insert(InputIterator first, InputIterator last);
355*6777b538SAndroid Build Coastguard Worker 
356*6777b538SAndroid Build Coastguard Worker   template <typename... Args>
357*6777b538SAndroid Build Coastguard Worker   const_iterator emplace(Args&&... args);
358*6777b538SAndroid Build Coastguard Worker 
359*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
360*6777b538SAndroid Build Coastguard Worker   // Removing elements.
361*6777b538SAndroid Build Coastguard Worker   //
362*6777b538SAndroid Build Coastguard Worker   // Erasing invalidates all outstanding iterators, pointers and references.
363*6777b538SAndroid Build Coastguard Worker   // Handles remain valid. Removing one element is amortized O(lg size)
364*6777b538SAndroid Build Coastguard Worker   // (occasional O(size) cost if a new vector allocation is required).
365*6777b538SAndroid Build Coastguard Worker   //
366*6777b538SAndroid Build Coastguard Worker   // Note that it is safe for the element being removed to be in an invalid
367*6777b538SAndroid Build Coastguard Worker   // state (modified such that it may currently violate the heap property)
368*6777b538SAndroid Build Coastguard Worker   // when this called.
369*6777b538SAndroid Build Coastguard Worker 
370*6777b538SAndroid Build Coastguard Worker   // Takes the element from the heap at the given position, erasing that entry
371*6777b538SAndroid Build Coastguard Worker   // from the heap. This can only be called if |value_type| is movable.
372*6777b538SAndroid Build Coastguard Worker   value_type take(size_type pos);
373*6777b538SAndroid Build Coastguard Worker 
374*6777b538SAndroid Build Coastguard Worker   // Version of take that will accept iterators and handles. This can only be
375*6777b538SAndroid Build Coastguard Worker   // called if |value_type| is movable.
376*6777b538SAndroid Build Coastguard Worker   template <typename P>
take(P pos)377*6777b538SAndroid Build Coastguard Worker   value_type take(P pos) {
378*6777b538SAndroid Build Coastguard Worker     return take(ToIndex(pos));
379*6777b538SAndroid Build Coastguard Worker   }
380*6777b538SAndroid Build Coastguard Worker 
381*6777b538SAndroid Build Coastguard Worker   // Takes the top element from the heap.
take_top()382*6777b538SAndroid Build Coastguard Worker   value_type take_top() { return take(0u); }
383*6777b538SAndroid Build Coastguard Worker 
384*6777b538SAndroid Build Coastguard Worker   // Erases the element at the given position |pos|.
385*6777b538SAndroid Build Coastguard Worker   void erase(size_type pos);
386*6777b538SAndroid Build Coastguard Worker 
387*6777b538SAndroid Build Coastguard Worker   // Version of erase that will accept iterators and handles.
388*6777b538SAndroid Build Coastguard Worker   template <typename P>
erase(P pos)389*6777b538SAndroid Build Coastguard Worker   void erase(P pos) {
390*6777b538SAndroid Build Coastguard Worker     erase(ToIndex(pos));
391*6777b538SAndroid Build Coastguard Worker   }
392*6777b538SAndroid Build Coastguard Worker 
393*6777b538SAndroid Build Coastguard Worker   // Removes the element at the top of the heap (accessible via "top", or
394*6777b538SAndroid Build Coastguard Worker   // "front" or "take").
pop()395*6777b538SAndroid Build Coastguard Worker   void pop() { erase(0u); }
396*6777b538SAndroid Build Coastguard Worker 
397*6777b538SAndroid Build Coastguard Worker   // Erases every element that matches the predicate. This is done in-place for
398*6777b538SAndroid Build Coastguard Worker   // maximum efficiency. Also, to avoid re-entrancy issues, elements are deleted
399*6777b538SAndroid Build Coastguard Worker   // at the very end.
400*6777b538SAndroid Build Coastguard Worker   // Note: This function is currently tuned for a use-case where there are
401*6777b538SAndroid Build Coastguard Worker   // usually 8 or less elements removed at a time. Consider adding a template
402*6777b538SAndroid Build Coastguard Worker   // parameter if a different tuning is needed.
403*6777b538SAndroid Build Coastguard Worker   template <typename Functor>
EraseIf(Functor predicate)404*6777b538SAndroid Build Coastguard Worker   void EraseIf(Functor predicate) {
405*6777b538SAndroid Build Coastguard Worker     // Stable partition ensures that if no elements are erased, the heap remains
406*6777b538SAndroid Build Coastguard Worker     // intact.
407*6777b538SAndroid Build Coastguard Worker     auto erase_start = std::stable_partition(
408*6777b538SAndroid Build Coastguard Worker         impl_.heap_.begin(), impl_.heap_.end(),
409*6777b538SAndroid Build Coastguard Worker         [&](const auto& element) { return !predicate(element); });
410*6777b538SAndroid Build Coastguard Worker 
411*6777b538SAndroid Build Coastguard Worker     // Clear the heap handle of every element that will be erased.
412*6777b538SAndroid Build Coastguard Worker     for (size_t i = static_cast<size_t>(erase_start - impl_.heap_.begin());
413*6777b538SAndroid Build Coastguard Worker          i < impl_.heap_.size(); ++i) {
414*6777b538SAndroid Build Coastguard Worker       ClearHeapHandle(i);
415*6777b538SAndroid Build Coastguard Worker     }
416*6777b538SAndroid Build Coastguard Worker 
417*6777b538SAndroid Build Coastguard Worker     // Deleting an element can potentially lead to reentrancy, we move all the
418*6777b538SAndroid Build Coastguard Worker     // elements to be erased into a temporary container before deleting them.
419*6777b538SAndroid Build Coastguard Worker     // This is to avoid changing the underlying container during the erase()
420*6777b538SAndroid Build Coastguard Worker     // call.
421*6777b538SAndroid Build Coastguard Worker     absl::InlinedVector<value_type, 8> elements_to_delete;
422*6777b538SAndroid Build Coastguard Worker     std::move(erase_start, impl_.heap_.end(),
423*6777b538SAndroid Build Coastguard Worker               std::back_inserter(elements_to_delete));
424*6777b538SAndroid Build Coastguard Worker 
425*6777b538SAndroid Build Coastguard Worker     impl_.heap_.erase(erase_start, impl_.heap_.end());
426*6777b538SAndroid Build Coastguard Worker 
427*6777b538SAndroid Build Coastguard Worker     // If no elements were removed, then the heap is still intact.
428*6777b538SAndroid Build Coastguard Worker     if (elements_to_delete.empty()) {
429*6777b538SAndroid Build Coastguard Worker       return;
430*6777b538SAndroid Build Coastguard Worker     }
431*6777b538SAndroid Build Coastguard Worker 
432*6777b538SAndroid Build Coastguard Worker     // Repair the heap and ensure handles are pointing to the right index.
433*6777b538SAndroid Build Coastguard Worker     ranges::make_heap(impl_.heap_, value_comp());
434*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < size(); ++i)
435*6777b538SAndroid Build Coastguard Worker       SetHeapHandle(i);
436*6777b538SAndroid Build Coastguard Worker 
437*6777b538SAndroid Build Coastguard Worker     // Explicitly delete elements last.
438*6777b538SAndroid Build Coastguard Worker     elements_to_delete.clear();
439*6777b538SAndroid Build Coastguard Worker   }
440*6777b538SAndroid Build Coastguard Worker 
441*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
442*6777b538SAndroid Build Coastguard Worker   // Updating.
443*6777b538SAndroid Build Coastguard Worker   //
444*6777b538SAndroid Build Coastguard Worker   // Amortized cost of O(lg size).
445*6777b538SAndroid Build Coastguard Worker 
446*6777b538SAndroid Build Coastguard Worker   // Replaces the element corresponding to |handle| with a new |element|.
Replace(size_type pos,const T & element)447*6777b538SAndroid Build Coastguard Worker   const_iterator Replace(size_type pos, const T& element) {
448*6777b538SAndroid Build Coastguard Worker     return ReplaceImpl(pos, element);
449*6777b538SAndroid Build Coastguard Worker   }
Replace(size_type pos,T && element)450*6777b538SAndroid Build Coastguard Worker   const_iterator Replace(size_type pos, T&& element) {
451*6777b538SAndroid Build Coastguard Worker     return ReplaceImpl(pos, std::move_if_noexcept(element));
452*6777b538SAndroid Build Coastguard Worker   }
453*6777b538SAndroid Build Coastguard Worker 
454*6777b538SAndroid Build Coastguard Worker   // Versions of Replace that will accept handles and iterators.
455*6777b538SAndroid Build Coastguard Worker   template <typename P>
Replace(P pos,const T & element)456*6777b538SAndroid Build Coastguard Worker   const_iterator Replace(P pos, const T& element) {
457*6777b538SAndroid Build Coastguard Worker     return ReplaceImpl(ToIndex(pos), element);
458*6777b538SAndroid Build Coastguard Worker   }
459*6777b538SAndroid Build Coastguard Worker   template <typename P>
Replace(P pos,T && element)460*6777b538SAndroid Build Coastguard Worker   const_iterator Replace(P pos, T&& element) {
461*6777b538SAndroid Build Coastguard Worker     return ReplaceImpl(ToIndex(pos), std::move_if_noexcept(element));
462*6777b538SAndroid Build Coastguard Worker   }
463*6777b538SAndroid Build Coastguard Worker 
464*6777b538SAndroid Build Coastguard Worker   // Replaces the top element in the heap with the provided element.
ReplaceTop(const T & element)465*6777b538SAndroid Build Coastguard Worker   const_iterator ReplaceTop(const T& element) {
466*6777b538SAndroid Build Coastguard Worker     return ReplaceTopImpl(element);
467*6777b538SAndroid Build Coastguard Worker   }
ReplaceTop(T && element)468*6777b538SAndroid Build Coastguard Worker   const_iterator ReplaceTop(T&& element) {
469*6777b538SAndroid Build Coastguard Worker     return ReplaceTopImpl(std::move_if_noexcept(element));
470*6777b538SAndroid Build Coastguard Worker   }
471*6777b538SAndroid Build Coastguard Worker 
472*6777b538SAndroid Build Coastguard Worker   // Causes the object at the given location to be resorted into an appropriate
473*6777b538SAndroid Build Coastguard Worker   // position in the heap. To be used if the object in the heap was externally
474*6777b538SAndroid Build Coastguard Worker   // modified, and the heap needs to be repaired. This only works if a single
475*6777b538SAndroid Build Coastguard Worker   // heap element has been modified, otherwise the behaviour is undefined.
476*6777b538SAndroid Build Coastguard Worker   const_iterator Update(size_type pos);
477*6777b538SAndroid Build Coastguard Worker   template <typename P>
Update(P pos)478*6777b538SAndroid Build Coastguard Worker   const_iterator Update(P pos) {
479*6777b538SAndroid Build Coastguard Worker     return Update(ToIndex(pos));
480*6777b538SAndroid Build Coastguard Worker   }
481*6777b538SAndroid Build Coastguard Worker 
482*6777b538SAndroid Build Coastguard Worker   // Applies a modification function to the object at the given location, then
483*6777b538SAndroid Build Coastguard Worker   // repairs the heap. To be used to modify an element in the heap in-place
484*6777b538SAndroid Build Coastguard Worker   // while keeping the heap intact.
485*6777b538SAndroid Build Coastguard Worker   template <typename P, typename UnaryOperation>
Modify(P pos,UnaryOperation unary_op)486*6777b538SAndroid Build Coastguard Worker   const_iterator Modify(P pos, UnaryOperation unary_op) {
487*6777b538SAndroid Build Coastguard Worker     size_type index = ToIndex(pos);
488*6777b538SAndroid Build Coastguard Worker     unary_op(impl_.heap_.at(index));
489*6777b538SAndroid Build Coastguard Worker     return Update(index);
490*6777b538SAndroid Build Coastguard Worker   }
491*6777b538SAndroid Build Coastguard Worker 
492*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
493*6777b538SAndroid Build Coastguard Worker   // Access to helper functors.
494*6777b538SAndroid Build Coastguard Worker 
value_comp()495*6777b538SAndroid Build Coastguard Worker   const value_compare& value_comp() const { return impl_.get_value_compare(); }
496*6777b538SAndroid Build Coastguard Worker 
heap_handle_access()497*6777b538SAndroid Build Coastguard Worker   const heap_handle_accessor& heap_handle_access() const {
498*6777b538SAndroid Build Coastguard Worker     return impl_.get_heap_handle_access();
499*6777b538SAndroid Build Coastguard Worker   }
500*6777b538SAndroid Build Coastguard Worker 
501*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
502*6777b538SAndroid Build Coastguard Worker   // General operations.
503*6777b538SAndroid Build Coastguard Worker 
504*6777b538SAndroid Build Coastguard Worker   void swap(IntrusiveHeap& other) noexcept;
swap(IntrusiveHeap & lhs,IntrusiveHeap & rhs)505*6777b538SAndroid Build Coastguard Worker   friend void swap(IntrusiveHeap& lhs, IntrusiveHeap& rhs) { lhs.swap(rhs); }
506*6777b538SAndroid Build Coastguard Worker 
507*6777b538SAndroid Build Coastguard Worker   // Comparison operators. These check for exact equality. Two heaps that are
508*6777b538SAndroid Build Coastguard Worker   // semantically equivalent (contain the same elements, but in different
509*6777b538SAndroid Build Coastguard Worker   // orders) won't compare as equal using these operators.
510*6777b538SAndroid Build Coastguard Worker   friend bool operator==(const IntrusiveHeap& lhs, const IntrusiveHeap& rhs) {
511*6777b538SAndroid Build Coastguard Worker     return lhs.impl_.heap_ == rhs.impl_.heap_;
512*6777b538SAndroid Build Coastguard Worker   }
513*6777b538SAndroid Build Coastguard Worker 
514*6777b538SAndroid Build Coastguard Worker   //////////////////////////////////////////////////////////////////////////////
515*6777b538SAndroid Build Coastguard Worker   // Utility functions.
516*6777b538SAndroid Build Coastguard Worker 
517*6777b538SAndroid Build Coastguard Worker   // Converts iterators and handles to indices. Helpers for templated versions
518*6777b538SAndroid Build Coastguard Worker   // of insert/erase/Replace.
ToIndex(HeapHandle handle)519*6777b538SAndroid Build Coastguard Worker   size_type ToIndex(HeapHandle handle) { return handle.index(); }
520*6777b538SAndroid Build Coastguard Worker   size_type ToIndex(const_iterator pos);
521*6777b538SAndroid Build Coastguard Worker   size_type ToIndex(const_reverse_iterator pos);
522*6777b538SAndroid Build Coastguard Worker 
523*6777b538SAndroid Build Coastguard Worker  private:
524*6777b538SAndroid Build Coastguard Worker   // Templated version of ToIndex that lets insert/erase/Replace work with all
525*6777b538SAndroid Build Coastguard Worker   // integral types.
526*6777b538SAndroid Build Coastguard Worker   template <typename I, typename = std::enable_if_t<std::is_integral_v<I>>>
ToIndex(I pos)527*6777b538SAndroid Build Coastguard Worker   size_type ToIndex(I pos) {
528*6777b538SAndroid Build Coastguard Worker     return static_cast<size_type>(pos);
529*6777b538SAndroid Build Coastguard Worker   }
530*6777b538SAndroid Build Coastguard Worker 
531*6777b538SAndroid Build Coastguard Worker   // Returns the last valid index in |heap_|.
GetLastIndex()532*6777b538SAndroid Build Coastguard Worker   size_type GetLastIndex() const { return impl_.heap_.size() - 1; }
533*6777b538SAndroid Build Coastguard Worker 
534*6777b538SAndroid Build Coastguard Worker   // Helper functions for setting heap handles.
535*6777b538SAndroid Build Coastguard Worker   void SetHeapHandle(size_type i);
536*6777b538SAndroid Build Coastguard Worker   void ClearHeapHandle(size_type i);
537*6777b538SAndroid Build Coastguard Worker   HeapHandle GetHeapHandle(size_type i);
538*6777b538SAndroid Build Coastguard Worker 
539*6777b538SAndroid Build Coastguard Worker   // Helpers for doing comparisons between elements inside and outside of the
540*6777b538SAndroid Build Coastguard Worker   // heap.
541*6777b538SAndroid Build Coastguard Worker   bool Less(size_type i, size_type j);
542*6777b538SAndroid Build Coastguard Worker   bool Less(const T& element, size_type i);
543*6777b538SAndroid Build Coastguard Worker   bool Less(size_type i, const T& element);
544*6777b538SAndroid Build Coastguard Worker 
545*6777b538SAndroid Build Coastguard Worker   // The following function are all related to the basic heap algorithm
546*6777b538SAndroid Build Coastguard Worker   // underpinning this data structure. They are templated so that they work with
547*6777b538SAndroid Build Coastguard Worker   // both movable (U = T&&) and non-movable (U = const T&) types.
548*6777b538SAndroid Build Coastguard Worker 
549*6777b538SAndroid Build Coastguard Worker   // Primitive helpers for adding removing / elements to the heap. To minimize
550*6777b538SAndroid Build Coastguard Worker   // moves, the heap is implemented by making a hole where an element used to
551*6777b538SAndroid Build Coastguard Worker   // be (or where a new element will soon be), and moving the hole around,
552*6777b538SAndroid Build Coastguard Worker   // before finally filling the hole or deleting the entry corresponding to the
553*6777b538SAndroid Build Coastguard Worker   // hole.
554*6777b538SAndroid Build Coastguard Worker   void MakeHole(size_type pos);
555*6777b538SAndroid Build Coastguard Worker   template <typename U>
556*6777b538SAndroid Build Coastguard Worker   void FillHole(size_type hole, U element);
557*6777b538SAndroid Build Coastguard Worker   void MoveHole(size_type new_hole_pos, size_type old_hole_pos);
558*6777b538SAndroid Build Coastguard Worker 
559*6777b538SAndroid Build Coastguard Worker   // Moves a hold up the tree and fills it with the provided |element|. Returns
560*6777b538SAndroid Build Coastguard Worker   // the final index of the element.
561*6777b538SAndroid Build Coastguard Worker   template <typename U>
562*6777b538SAndroid Build Coastguard Worker   size_type MoveHoleUpAndFill(size_type hole_pos, U element);
563*6777b538SAndroid Build Coastguard Worker 
564*6777b538SAndroid Build Coastguard Worker   // Moves a hole down the tree and fills it with the provided |element|. If
565*6777b538SAndroid Build Coastguard Worker   // |kFillWithLeaf| is true it will deterministically move the hole all the
566*6777b538SAndroid Build Coastguard Worker   // way down the tree, avoiding a second comparison per level, before
567*6777b538SAndroid Build Coastguard Worker   // potentially moving it back up the tree.
568*6777b538SAndroid Build Coastguard Worker   struct WithLeafElement {
569*6777b538SAndroid Build Coastguard Worker     static constexpr bool kIsLeafElement = true;
570*6777b538SAndroid Build Coastguard Worker   };
571*6777b538SAndroid Build Coastguard Worker   struct WithElement {
572*6777b538SAndroid Build Coastguard Worker     static constexpr bool kIsLeafElement = false;
573*6777b538SAndroid Build Coastguard Worker   };
574*6777b538SAndroid Build Coastguard Worker   template <typename FillElementType, typename U>
575*6777b538SAndroid Build Coastguard Worker   size_type MoveHoleDownAndFill(size_type hole_pos, U element);
576*6777b538SAndroid Build Coastguard Worker 
577*6777b538SAndroid Build Coastguard Worker   // Implementation of Insert and Replace built on top of the MoveHole
578*6777b538SAndroid Build Coastguard Worker   // primitives.
579*6777b538SAndroid Build Coastguard Worker   template <typename U>
580*6777b538SAndroid Build Coastguard Worker   const_iterator InsertImpl(U element);
581*6777b538SAndroid Build Coastguard Worker   template <typename U>
582*6777b538SAndroid Build Coastguard Worker   const_iterator ReplaceImpl(size_type pos, U element);
583*6777b538SAndroid Build Coastguard Worker   template <typename U>
584*6777b538SAndroid Build Coastguard Worker   const_iterator ReplaceTopImpl(U element);
585*6777b538SAndroid Build Coastguard Worker 
586*6777b538SAndroid Build Coastguard Worker   // To support comparators that may not be possible to default-construct, we
587*6777b538SAndroid Build Coastguard Worker   // have to store an instance of value_compare. Using this to store all
588*6777b538SAndroid Build Coastguard Worker   // internal state of IntrusiveHeap and using private inheritance to store
589*6777b538SAndroid Build Coastguard Worker   // compare lets us take advantage of an empty base class optimization to avoid
590*6777b538SAndroid Build Coastguard Worker   // extra space in the common case when Compare has no state.
591*6777b538SAndroid Build Coastguard Worker   struct Impl : private value_compare, private heap_handle_accessor {
ImplImpl592*6777b538SAndroid Build Coastguard Worker     Impl(const value_compare& value_comp,
593*6777b538SAndroid Build Coastguard Worker          const heap_handle_accessor& heap_handle_access)
594*6777b538SAndroid Build Coastguard Worker         : value_compare(value_comp), heap_handle_accessor(heap_handle_access) {}
595*6777b538SAndroid Build Coastguard Worker 
596*6777b538SAndroid Build Coastguard Worker     Impl() = default;
597*6777b538SAndroid Build Coastguard Worker     Impl(Impl&&) = default;
598*6777b538SAndroid Build Coastguard Worker     Impl(const Impl&) = default;
599*6777b538SAndroid Build Coastguard Worker     Impl& operator=(Impl&& other) = default;
600*6777b538SAndroid Build Coastguard Worker     Impl& operator=(const Impl& other) = default;
601*6777b538SAndroid Build Coastguard Worker 
get_value_compareImpl602*6777b538SAndroid Build Coastguard Worker     const value_compare& get_value_compare() const { return *this; }
get_value_compareImpl603*6777b538SAndroid Build Coastguard Worker     value_compare& get_value_compare() { return *this; }
604*6777b538SAndroid Build Coastguard Worker 
get_heap_handle_accessImpl605*6777b538SAndroid Build Coastguard Worker     const heap_handle_accessor& get_heap_handle_access() const { return *this; }
get_heap_handle_accessImpl606*6777b538SAndroid Build Coastguard Worker     heap_handle_accessor& get_heap_handle_access() { return *this; }
607*6777b538SAndroid Build Coastguard Worker 
608*6777b538SAndroid Build Coastguard Worker     // The items in the heap.
609*6777b538SAndroid Build Coastguard Worker     UnderlyingType heap_;
610*6777b538SAndroid Build Coastguard Worker   } impl_;
611*6777b538SAndroid Build Coastguard Worker };
612*6777b538SAndroid Build Coastguard Worker 
613*6777b538SAndroid Build Coastguard Worker // Helper class to endow an object with internal HeapHandle storage. By deriving
614*6777b538SAndroid Build Coastguard Worker // from this type you endow your class with self-owned storage for a HeapHandle.
615*6777b538SAndroid Build Coastguard Worker // This is a move-only type so that the handle follows the element across moves
616*6777b538SAndroid Build Coastguard Worker // and resizes of the underlying vector.
617*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT InternalHeapHandleStorage {
618*6777b538SAndroid Build Coastguard Worker  public:
619*6777b538SAndroid Build Coastguard Worker   InternalHeapHandleStorage();
620*6777b538SAndroid Build Coastguard Worker   InternalHeapHandleStorage(const InternalHeapHandleStorage&) = delete;
621*6777b538SAndroid Build Coastguard Worker   InternalHeapHandleStorage(InternalHeapHandleStorage&& other) noexcept;
622*6777b538SAndroid Build Coastguard Worker   virtual ~InternalHeapHandleStorage();
623*6777b538SAndroid Build Coastguard Worker 
624*6777b538SAndroid Build Coastguard Worker   InternalHeapHandleStorage& operator=(const InternalHeapHandleStorage&) =
625*6777b538SAndroid Build Coastguard Worker       delete;
626*6777b538SAndroid Build Coastguard Worker   InternalHeapHandleStorage& operator=(
627*6777b538SAndroid Build Coastguard Worker       InternalHeapHandleStorage&& other) noexcept;
628*6777b538SAndroid Build Coastguard Worker 
629*6777b538SAndroid Build Coastguard Worker   // Allows external clients to get a pointer to the heap handle. This allows
630*6777b538SAndroid Build Coastguard Worker   // them to remove the element from the heap regardless of its location.
handle()631*6777b538SAndroid Build Coastguard Worker   HeapHandle* handle() const { return handle_.get(); }
632*6777b538SAndroid Build Coastguard Worker 
633*6777b538SAndroid Build Coastguard Worker   // Implementation of IntrusiveHeap contract. Inlined to keep heap code as fast
634*6777b538SAndroid Build Coastguard Worker   // as possible.
SetHeapHandle(HeapHandle handle)635*6777b538SAndroid Build Coastguard Worker   void SetHeapHandle(HeapHandle handle) {
636*6777b538SAndroid Build Coastguard Worker     DCHECK(handle.IsValid());
637*6777b538SAndroid Build Coastguard Worker     if (handle_)
638*6777b538SAndroid Build Coastguard Worker       *handle_ = handle;
639*6777b538SAndroid Build Coastguard Worker   }
ClearHeapHandle()640*6777b538SAndroid Build Coastguard Worker   void ClearHeapHandle() {
641*6777b538SAndroid Build Coastguard Worker     if (handle_)
642*6777b538SAndroid Build Coastguard Worker       handle_->reset();
643*6777b538SAndroid Build Coastguard Worker   }
GetHeapHandle()644*6777b538SAndroid Build Coastguard Worker   HeapHandle GetHeapHandle() const {
645*6777b538SAndroid Build Coastguard Worker     if (handle_)
646*6777b538SAndroid Build Coastguard Worker       return *handle_;
647*6777b538SAndroid Build Coastguard Worker     return HeapHandle::Invalid();
648*6777b538SAndroid Build Coastguard Worker   }
649*6777b538SAndroid Build Coastguard Worker 
650*6777b538SAndroid Build Coastguard Worker   // Utility functions.
651*6777b538SAndroid Build Coastguard Worker   void swap(InternalHeapHandleStorage& other) noexcept;
swap(InternalHeapHandleStorage & lhs,InternalHeapHandleStorage & rhs)652*6777b538SAndroid Build Coastguard Worker   friend void swap(InternalHeapHandleStorage& lhs,
653*6777b538SAndroid Build Coastguard Worker                    InternalHeapHandleStorage& rhs) {
654*6777b538SAndroid Build Coastguard Worker     lhs.swap(rhs);
655*6777b538SAndroid Build Coastguard Worker   }
656*6777b538SAndroid Build Coastguard Worker 
657*6777b538SAndroid Build Coastguard Worker  private:
658*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<HeapHandle> handle_;
659*6777b538SAndroid Build Coastguard Worker };
660*6777b538SAndroid Build Coastguard Worker 
661*6777b538SAndroid Build Coastguard Worker // Spiritually akin to a std::pair<T, std::unique_ptr<HeapHandle>>. Can be used
662*6777b538SAndroid Build Coastguard Worker // to wrap arbitrary types and provide them with a HeapHandle, making them
663*6777b538SAndroid Build Coastguard Worker // appropriate for use in an IntrusiveHeap. This is a move-only type.
664*6777b538SAndroid Build Coastguard Worker template <typename T>
665*6777b538SAndroid Build Coastguard Worker class WithHeapHandle : public InternalHeapHandleStorage {
666*6777b538SAndroid Build Coastguard Worker  public:
667*6777b538SAndroid Build Coastguard Worker   WithHeapHandle() = default;
668*6777b538SAndroid Build Coastguard Worker   // Allow implicit conversion of any type that T supports for ease of use with
669*6777b538SAndroid Build Coastguard Worker   // InstrusiveHeap constructors/insert/emplace.
670*6777b538SAndroid Build Coastguard Worker   template <typename U>
WithHeapHandle(U value)671*6777b538SAndroid Build Coastguard Worker   WithHeapHandle(U value) : value_(std::move_if_noexcept(value)) {}
WithHeapHandle(T && value)672*6777b538SAndroid Build Coastguard Worker   WithHeapHandle(T&& value) noexcept : value_(std::move(value)) {}
673*6777b538SAndroid Build Coastguard Worker   // Constructor that forwards all arguments along to |value_|.
674*6777b538SAndroid Build Coastguard Worker   template <class... Args>
675*6777b538SAndroid Build Coastguard Worker   explicit WithHeapHandle(Args&&... args);
676*6777b538SAndroid Build Coastguard Worker   WithHeapHandle(const WithHeapHandle&) = delete;
677*6777b538SAndroid Build Coastguard Worker   WithHeapHandle(WithHeapHandle&& other) noexcept = default;
678*6777b538SAndroid Build Coastguard Worker   ~WithHeapHandle() override = default;
679*6777b538SAndroid Build Coastguard Worker 
680*6777b538SAndroid Build Coastguard Worker   WithHeapHandle& operator=(const WithHeapHandle&) = delete;
681*6777b538SAndroid Build Coastguard Worker   WithHeapHandle& operator=(WithHeapHandle&& other) = default;
682*6777b538SAndroid Build Coastguard Worker 
value()683*6777b538SAndroid Build Coastguard Worker   T& value() { return value_; }
value()684*6777b538SAndroid Build Coastguard Worker   const T& value() const { return value_; }
685*6777b538SAndroid Build Coastguard Worker 
686*6777b538SAndroid Build Coastguard Worker   // Utility functions.
687*6777b538SAndroid Build Coastguard Worker   void swap(WithHeapHandle& other) noexcept;
swap(WithHeapHandle & lhs,WithHeapHandle & rhs)688*6777b538SAndroid Build Coastguard Worker   friend void swap(WithHeapHandle& lhs, WithHeapHandle& rhs) { lhs.swap(rhs); }
689*6777b538SAndroid Build Coastguard Worker 
690*6777b538SAndroid Build Coastguard Worker   // Comparison operators, for compatibility with ordered STL containers.
691*6777b538SAndroid Build Coastguard Worker   friend bool operator==(const WithHeapHandle& lhs, const WithHeapHandle& rhs) {
692*6777b538SAndroid Build Coastguard Worker     return lhs.value_ == rhs.value_;
693*6777b538SAndroid Build Coastguard Worker   }
694*6777b538SAndroid Build Coastguard Worker   friend auto operator<=>(const WithHeapHandle& lhs,
695*6777b538SAndroid Build Coastguard Worker                           const WithHeapHandle& rhs) {
696*6777b538SAndroid Build Coastguard Worker     return lhs.value_ <=> rhs.value_;
697*6777b538SAndroid Build Coastguard Worker   }
698*6777b538SAndroid Build Coastguard Worker 
699*6777b538SAndroid Build Coastguard Worker  private:
700*6777b538SAndroid Build Coastguard Worker   T value_;
701*6777b538SAndroid Build Coastguard Worker };
702*6777b538SAndroid Build Coastguard Worker 
703*6777b538SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
704*6777b538SAndroid Build Coastguard Worker // IMPLEMENTATION DETAILS
705*6777b538SAndroid Build Coastguard Worker 
706*6777b538SAndroid Build Coastguard Worker namespace intrusive_heap {
707*6777b538SAndroid Build Coastguard Worker 
ParentIndex(size_t i)708*6777b538SAndroid Build Coastguard Worker BASE_EXPORT inline size_t ParentIndex(size_t i) {
709*6777b538SAndroid Build Coastguard Worker   DCHECK_NE(0u, i);
710*6777b538SAndroid Build Coastguard Worker   return (i - 1) / 2;
711*6777b538SAndroid Build Coastguard Worker }
712*6777b538SAndroid Build Coastguard Worker 
LeftIndex(size_t i)713*6777b538SAndroid Build Coastguard Worker BASE_EXPORT inline size_t LeftIndex(size_t i) {
714*6777b538SAndroid Build Coastguard Worker   return 2 * i + 1;
715*6777b538SAndroid Build Coastguard Worker }
716*6777b538SAndroid Build Coastguard Worker 
717*6777b538SAndroid Build Coastguard Worker template <typename HandleType>
IsInvalid(const HandleType & handle)718*6777b538SAndroid Build Coastguard Worker bool IsInvalid(const HandleType& handle) {
719*6777b538SAndroid Build Coastguard Worker   return !handle || !handle->IsValid();
720*6777b538SAndroid Build Coastguard Worker }
721*6777b538SAndroid Build Coastguard Worker 
CheckInvalidOrEqualTo(HeapHandle handle,size_t index)722*6777b538SAndroid Build Coastguard Worker BASE_EXPORT inline void CheckInvalidOrEqualTo(HeapHandle handle, size_t index) {
723*6777b538SAndroid Build Coastguard Worker   if (handle.IsValid())
724*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(index, handle.index());
725*6777b538SAndroid Build Coastguard Worker }
726*6777b538SAndroid Build Coastguard Worker 
727*6777b538SAndroid Build Coastguard Worker }  // namespace intrusive_heap
728*6777b538SAndroid Build Coastguard Worker 
729*6777b538SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
730*6777b538SAndroid Build Coastguard Worker // IntrusiveHeap
731*6777b538SAndroid Build Coastguard Worker 
732*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
IntrusiveHeap(const IntrusiveHeap & other)733*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::IntrusiveHeap(
734*6777b538SAndroid Build Coastguard Worker     const IntrusiveHeap& other)
735*6777b538SAndroid Build Coastguard Worker     : impl_(other.impl_) {
736*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < size(); ++i) {
737*6777b538SAndroid Build Coastguard Worker     SetHeapHandle(i);
738*6777b538SAndroid Build Coastguard Worker   }
739*6777b538SAndroid Build Coastguard Worker }
740*6777b538SAndroid Build Coastguard Worker 
741*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
~IntrusiveHeap()742*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::~IntrusiveHeap() {
743*6777b538SAndroid Build Coastguard Worker   clear();
744*6777b538SAndroid Build Coastguard Worker }
745*6777b538SAndroid Build Coastguard Worker 
746*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
747*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>&
748*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::operator=(
749*6777b538SAndroid Build Coastguard Worker     IntrusiveHeap&& other) noexcept {
750*6777b538SAndroid Build Coastguard Worker   clear();
751*6777b538SAndroid Build Coastguard Worker   impl_ = std::move(other.impl_);
752*6777b538SAndroid Build Coastguard Worker   return *this;
753*6777b538SAndroid Build Coastguard Worker }
754*6777b538SAndroid Build Coastguard Worker 
755*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
756*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>&
757*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::operator=(
758*6777b538SAndroid Build Coastguard Worker     const IntrusiveHeap& other) {
759*6777b538SAndroid Build Coastguard Worker   clear();
760*6777b538SAndroid Build Coastguard Worker   impl_ = other.impl_;
761*6777b538SAndroid Build Coastguard Worker   for (size_t i = 0; i < size(); ++i) {
762*6777b538SAndroid Build Coastguard Worker     SetHeapHandle(i);
763*6777b538SAndroid Build Coastguard Worker   }
764*6777b538SAndroid Build Coastguard Worker   return *this;
765*6777b538SAndroid Build Coastguard Worker }
766*6777b538SAndroid Build Coastguard Worker 
767*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
768*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>&
769*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::operator=(
770*6777b538SAndroid Build Coastguard Worker     std::initializer_list<value_type> ilist) {
771*6777b538SAndroid Build Coastguard Worker   clear();
772*6777b538SAndroid Build Coastguard Worker   insert(std::begin(ilist), std::end(ilist));
773*6777b538SAndroid Build Coastguard Worker }
774*6777b538SAndroid Build Coastguard Worker 
775*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
clear()776*6777b538SAndroid Build Coastguard Worker void IntrusiveHeap<T, Compare, HeapHandleAccessor>::clear() {
777*6777b538SAndroid Build Coastguard Worker   // Make all of the handles invalid before cleaning up the heap.
778*6777b538SAndroid Build Coastguard Worker   for (size_type i = 0; i < size(); ++i) {
779*6777b538SAndroid Build Coastguard Worker     ClearHeapHandle(i);
780*6777b538SAndroid Build Coastguard Worker   }
781*6777b538SAndroid Build Coastguard Worker 
782*6777b538SAndroid Build Coastguard Worker   // Clear the heap.
783*6777b538SAndroid Build Coastguard Worker   impl_.heap_.clear();
784*6777b538SAndroid Build Coastguard Worker }
785*6777b538SAndroid Build Coastguard Worker 
786*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
787*6777b538SAndroid Build Coastguard Worker template <class InputIterator>
insert(InputIterator first,InputIterator last)788*6777b538SAndroid Build Coastguard Worker void IntrusiveHeap<T, Compare, HeapHandleAccessor>::insert(InputIterator first,
789*6777b538SAndroid Build Coastguard Worker                                                            InputIterator last) {
790*6777b538SAndroid Build Coastguard Worker   for (auto it = first; it != last; ++it) {
791*6777b538SAndroid Build Coastguard Worker     insert(value_type(*it));
792*6777b538SAndroid Build Coastguard Worker   }
793*6777b538SAndroid Build Coastguard Worker }
794*6777b538SAndroid Build Coastguard Worker 
795*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
796*6777b538SAndroid Build Coastguard Worker template <typename... Args>
797*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::const_iterator
emplace(Args &&...args)798*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::emplace(Args&&... args) {
799*6777b538SAndroid Build Coastguard Worker   value_type value(std::forward<Args>(args)...);
800*6777b538SAndroid Build Coastguard Worker   return InsertImpl(std::move_if_noexcept(value));
801*6777b538SAndroid Build Coastguard Worker }
802*6777b538SAndroid Build Coastguard Worker 
803*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
804*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::value_type
take(size_type pos)805*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::take(size_type pos) {
806*6777b538SAndroid Build Coastguard Worker   // Make a hole by taking the element out of the heap.
807*6777b538SAndroid Build Coastguard Worker   MakeHole(pos);
808*6777b538SAndroid Build Coastguard Worker   value_type val = std::move(impl_.heap_[pos]);
809*6777b538SAndroid Build Coastguard Worker 
810*6777b538SAndroid Build Coastguard Worker   // If the element being taken is already the last element then the heap
811*6777b538SAndroid Build Coastguard Worker   // doesn't need to be repaired.
812*6777b538SAndroid Build Coastguard Worker   if (pos != GetLastIndex()) {
813*6777b538SAndroid Build Coastguard Worker     MakeHole(GetLastIndex());
814*6777b538SAndroid Build Coastguard Worker 
815*6777b538SAndroid Build Coastguard Worker     // Move the hole down the heap, filling it with the current leaf at the
816*6777b538SAndroid Build Coastguard Worker     // very end of the heap.
817*6777b538SAndroid Build Coastguard Worker     MoveHoleDownAndFill<WithLeafElement>(
818*6777b538SAndroid Build Coastguard Worker         pos, std::move(impl_.heap_[GetLastIndex()]));
819*6777b538SAndroid Build Coastguard Worker   }
820*6777b538SAndroid Build Coastguard Worker 
821*6777b538SAndroid Build Coastguard Worker   impl_.heap_.pop_back();
822*6777b538SAndroid Build Coastguard Worker 
823*6777b538SAndroid Build Coastguard Worker   return val;
824*6777b538SAndroid Build Coastguard Worker }
825*6777b538SAndroid Build Coastguard Worker 
826*6777b538SAndroid Build Coastguard Worker // This is effectively identical to "take", but it avoids an unnecessary move.
827*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
erase(size_type pos)828*6777b538SAndroid Build Coastguard Worker void IntrusiveHeap<T, Compare, HeapHandleAccessor>::erase(size_type pos) {
829*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(pos, size());
830*6777b538SAndroid Build Coastguard Worker   // Make a hole by taking the element out of the heap.
831*6777b538SAndroid Build Coastguard Worker   MakeHole(pos);
832*6777b538SAndroid Build Coastguard Worker 
833*6777b538SAndroid Build Coastguard Worker   // If the element being erased is already the last element then the heap
834*6777b538SAndroid Build Coastguard Worker   // doesn't need to be repaired.
835*6777b538SAndroid Build Coastguard Worker   if (pos != GetLastIndex()) {
836*6777b538SAndroid Build Coastguard Worker     MakeHole(GetLastIndex());
837*6777b538SAndroid Build Coastguard Worker 
838*6777b538SAndroid Build Coastguard Worker     // Move the hole down the heap, filling it with the current leaf at the
839*6777b538SAndroid Build Coastguard Worker     // very end of the heap.
840*6777b538SAndroid Build Coastguard Worker     MoveHoleDownAndFill<WithLeafElement>(
841*6777b538SAndroid Build Coastguard Worker         pos, std::move_if_noexcept(impl_.heap_[GetLastIndex()]));
842*6777b538SAndroid Build Coastguard Worker   }
843*6777b538SAndroid Build Coastguard Worker 
844*6777b538SAndroid Build Coastguard Worker   impl_.heap_.pop_back();
845*6777b538SAndroid Build Coastguard Worker }
846*6777b538SAndroid Build Coastguard Worker 
847*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
848*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::const_iterator
Update(size_type pos)849*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::Update(size_type pos) {
850*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(pos, size());
851*6777b538SAndroid Build Coastguard Worker   MakeHole(pos);
852*6777b538SAndroid Build Coastguard Worker 
853*6777b538SAndroid Build Coastguard Worker   // Determine if we're >= parent, in which case we may need to go up.
854*6777b538SAndroid Build Coastguard Worker   bool child_greater_eq_parent = false;
855*6777b538SAndroid Build Coastguard Worker   size_type i = 0;
856*6777b538SAndroid Build Coastguard Worker   if (pos > 0) {
857*6777b538SAndroid Build Coastguard Worker     i = intrusive_heap::ParentIndex(pos);
858*6777b538SAndroid Build Coastguard Worker     child_greater_eq_parent = !Less(pos, i);
859*6777b538SAndroid Build Coastguard Worker   }
860*6777b538SAndroid Build Coastguard Worker 
861*6777b538SAndroid Build Coastguard Worker   if (child_greater_eq_parent) {
862*6777b538SAndroid Build Coastguard Worker     i = MoveHoleUpAndFill(pos, std::move_if_noexcept(impl_.heap_[pos]));
863*6777b538SAndroid Build Coastguard Worker   } else {
864*6777b538SAndroid Build Coastguard Worker     i = MoveHoleDownAndFill<WithElement>(
865*6777b538SAndroid Build Coastguard Worker         pos, std::move_if_noexcept(impl_.heap_[pos]));
866*6777b538SAndroid Build Coastguard Worker   }
867*6777b538SAndroid Build Coastguard Worker 
868*6777b538SAndroid Build Coastguard Worker   return cbegin() + i;
869*6777b538SAndroid Build Coastguard Worker }
870*6777b538SAndroid Build Coastguard Worker 
871*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
swap(IntrusiveHeap & other)872*6777b538SAndroid Build Coastguard Worker void IntrusiveHeap<T, Compare, HeapHandleAccessor>::swap(
873*6777b538SAndroid Build Coastguard Worker     IntrusiveHeap& other) noexcept {
874*6777b538SAndroid Build Coastguard Worker   std::swap(impl_.get_value_compare(), other.impl_.get_value_compare());
875*6777b538SAndroid Build Coastguard Worker   std::swap(impl_.get_heap_handle_access(),
876*6777b538SAndroid Build Coastguard Worker             other.impl_.get_heap_handle_access());
877*6777b538SAndroid Build Coastguard Worker   std::swap(impl_.heap_, other.impl_.heap_);
878*6777b538SAndroid Build Coastguard Worker }
879*6777b538SAndroid Build Coastguard Worker 
880*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
881*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::size_type
ToIndex(const_iterator pos)882*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::ToIndex(const_iterator pos) {
883*6777b538SAndroid Build Coastguard Worker   DCHECK(cbegin() <= pos);
884*6777b538SAndroid Build Coastguard Worker   DCHECK(pos <= cend());
885*6777b538SAndroid Build Coastguard Worker   if (pos == cend())
886*6777b538SAndroid Build Coastguard Worker     return HeapHandle::kInvalidIndex;
887*6777b538SAndroid Build Coastguard Worker   return pos - cbegin();
888*6777b538SAndroid Build Coastguard Worker }
889*6777b538SAndroid Build Coastguard Worker 
890*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
891*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::size_type
ToIndex(const_reverse_iterator pos)892*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::ToIndex(
893*6777b538SAndroid Build Coastguard Worker     const_reverse_iterator pos) {
894*6777b538SAndroid Build Coastguard Worker   DCHECK(crbegin() <= pos);
895*6777b538SAndroid Build Coastguard Worker   DCHECK(pos <= crend());
896*6777b538SAndroid Build Coastguard Worker   if (pos == crend())
897*6777b538SAndroid Build Coastguard Worker     return HeapHandle::kInvalidIndex;
898*6777b538SAndroid Build Coastguard Worker   return (pos.base() - cbegin()) - 1;
899*6777b538SAndroid Build Coastguard Worker }
900*6777b538SAndroid Build Coastguard Worker 
901*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
SetHeapHandle(size_type i)902*6777b538SAndroid Build Coastguard Worker void IntrusiveHeap<T, Compare, HeapHandleAccessor>::SetHeapHandle(size_type i) {
903*6777b538SAndroid Build Coastguard Worker   impl_.get_heap_handle_access().SetHeapHandle(&impl_.heap_[i], HeapHandle(i));
904*6777b538SAndroid Build Coastguard Worker   intrusive_heap::CheckInvalidOrEqualTo(GetHeapHandle(i), i);
905*6777b538SAndroid Build Coastguard Worker }
906*6777b538SAndroid Build Coastguard Worker 
907*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
ClearHeapHandle(size_type i)908*6777b538SAndroid Build Coastguard Worker void IntrusiveHeap<T, Compare, HeapHandleAccessor>::ClearHeapHandle(
909*6777b538SAndroid Build Coastguard Worker     size_type i) {
910*6777b538SAndroid Build Coastguard Worker   impl_.get_heap_handle_access().ClearHeapHandle(&impl_.heap_[i]);
911*6777b538SAndroid Build Coastguard Worker   DCHECK(!GetHeapHandle(i).IsValid());
912*6777b538SAndroid Build Coastguard Worker }
913*6777b538SAndroid Build Coastguard Worker 
914*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
GetHeapHandle(size_type i)915*6777b538SAndroid Build Coastguard Worker HeapHandle IntrusiveHeap<T, Compare, HeapHandleAccessor>::GetHeapHandle(
916*6777b538SAndroid Build Coastguard Worker     size_type i) {
917*6777b538SAndroid Build Coastguard Worker   return impl_.get_heap_handle_access().GetHeapHandle(&impl_.heap_[i]);
918*6777b538SAndroid Build Coastguard Worker }
919*6777b538SAndroid Build Coastguard Worker 
920*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
Less(size_type i,size_type j)921*6777b538SAndroid Build Coastguard Worker bool IntrusiveHeap<T, Compare, HeapHandleAccessor>::Less(size_type i,
922*6777b538SAndroid Build Coastguard Worker                                                          size_type j) {
923*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(i, size());
924*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(j, size());
925*6777b538SAndroid Build Coastguard Worker   return impl_.get_value_compare()(impl_.heap_[i], impl_.heap_[j]);
926*6777b538SAndroid Build Coastguard Worker }
927*6777b538SAndroid Build Coastguard Worker 
928*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
Less(const T & element,size_type i)929*6777b538SAndroid Build Coastguard Worker bool IntrusiveHeap<T, Compare, HeapHandleAccessor>::Less(const T& element,
930*6777b538SAndroid Build Coastguard Worker                                                          size_type i) {
931*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(i, size());
932*6777b538SAndroid Build Coastguard Worker   return impl_.get_value_compare()(element, impl_.heap_[i]);
933*6777b538SAndroid Build Coastguard Worker }
934*6777b538SAndroid Build Coastguard Worker 
935*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
Less(size_type i,const T & element)936*6777b538SAndroid Build Coastguard Worker bool IntrusiveHeap<T, Compare, HeapHandleAccessor>::Less(size_type i,
937*6777b538SAndroid Build Coastguard Worker                                                          const T& element) {
938*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(i, size());
939*6777b538SAndroid Build Coastguard Worker   return impl_.get_value_compare()(impl_.heap_[i], element);
940*6777b538SAndroid Build Coastguard Worker }
941*6777b538SAndroid Build Coastguard Worker 
942*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
MakeHole(size_type pos)943*6777b538SAndroid Build Coastguard Worker void IntrusiveHeap<T, Compare, HeapHandleAccessor>::MakeHole(size_type pos) {
944*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(pos, size());
945*6777b538SAndroid Build Coastguard Worker   ClearHeapHandle(pos);
946*6777b538SAndroid Build Coastguard Worker }
947*6777b538SAndroid Build Coastguard Worker 
948*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
949*6777b538SAndroid Build Coastguard Worker template <typename U>
FillHole(size_type hole_pos,U element)950*6777b538SAndroid Build Coastguard Worker void IntrusiveHeap<T, Compare, HeapHandleAccessor>::FillHole(size_type hole_pos,
951*6777b538SAndroid Build Coastguard Worker                                                              U element) {
952*6777b538SAndroid Build Coastguard Worker   // The hole that we're filling may not yet exist. This can occur when
953*6777b538SAndroid Build Coastguard Worker   // inserting a new element into the heap.
954*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(hole_pos, size());
955*6777b538SAndroid Build Coastguard Worker   if (hole_pos == size()) {
956*6777b538SAndroid Build Coastguard Worker     impl_.heap_.push_back(std::move_if_noexcept(element));
957*6777b538SAndroid Build Coastguard Worker   } else {
958*6777b538SAndroid Build Coastguard Worker     impl_.heap_[hole_pos] = std::move_if_noexcept(element);
959*6777b538SAndroid Build Coastguard Worker   }
960*6777b538SAndroid Build Coastguard Worker   SetHeapHandle(hole_pos);
961*6777b538SAndroid Build Coastguard Worker }
962*6777b538SAndroid Build Coastguard Worker 
963*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
MoveHole(size_type new_hole_pos,size_type old_hole_pos)964*6777b538SAndroid Build Coastguard Worker void IntrusiveHeap<T, Compare, HeapHandleAccessor>::MoveHole(
965*6777b538SAndroid Build Coastguard Worker     size_type new_hole_pos,
966*6777b538SAndroid Build Coastguard Worker     size_type old_hole_pos) {
967*6777b538SAndroid Build Coastguard Worker   // The old hole position may be one past the end. This occurs when a new
968*6777b538SAndroid Build Coastguard Worker   // element is being added.
969*6777b538SAndroid Build Coastguard Worker   DCHECK_NE(new_hole_pos, old_hole_pos);
970*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(new_hole_pos, size());
971*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(old_hole_pos, size());
972*6777b538SAndroid Build Coastguard Worker 
973*6777b538SAndroid Build Coastguard Worker   if (old_hole_pos == size()) {
974*6777b538SAndroid Build Coastguard Worker     impl_.heap_.push_back(std::move_if_noexcept(impl_.heap_[new_hole_pos]));
975*6777b538SAndroid Build Coastguard Worker   } else {
976*6777b538SAndroid Build Coastguard Worker     impl_.heap_[old_hole_pos] =
977*6777b538SAndroid Build Coastguard Worker         std::move_if_noexcept(impl_.heap_[new_hole_pos]);
978*6777b538SAndroid Build Coastguard Worker   }
979*6777b538SAndroid Build Coastguard Worker   SetHeapHandle(old_hole_pos);
980*6777b538SAndroid Build Coastguard Worker }
981*6777b538SAndroid Build Coastguard Worker 
982*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
983*6777b538SAndroid Build Coastguard Worker template <typename U>
984*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::size_type
MoveHoleUpAndFill(size_type hole_pos,U element)985*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::MoveHoleUpAndFill(
986*6777b538SAndroid Build Coastguard Worker     size_type hole_pos,
987*6777b538SAndroid Build Coastguard Worker     U element) {
988*6777b538SAndroid Build Coastguard Worker   // Moving 1 spot beyond the end is fine. This happens when we insert a new
989*6777b538SAndroid Build Coastguard Worker   // element.
990*6777b538SAndroid Build Coastguard Worker   DCHECK_LE(hole_pos, size());
991*6777b538SAndroid Build Coastguard Worker 
992*6777b538SAndroid Build Coastguard Worker   // Stop when the element is as far up as it can go.
993*6777b538SAndroid Build Coastguard Worker   while (hole_pos != 0) {
994*6777b538SAndroid Build Coastguard Worker     // If our parent is >= to us, we can stop.
995*6777b538SAndroid Build Coastguard Worker     size_type parent = intrusive_heap::ParentIndex(hole_pos);
996*6777b538SAndroid Build Coastguard Worker     if (!Less(parent, element))
997*6777b538SAndroid Build Coastguard Worker       break;
998*6777b538SAndroid Build Coastguard Worker 
999*6777b538SAndroid Build Coastguard Worker     MoveHole(parent, hole_pos);
1000*6777b538SAndroid Build Coastguard Worker     hole_pos = parent;
1001*6777b538SAndroid Build Coastguard Worker   }
1002*6777b538SAndroid Build Coastguard Worker 
1003*6777b538SAndroid Build Coastguard Worker   FillHole(hole_pos, std::move_if_noexcept(element));
1004*6777b538SAndroid Build Coastguard Worker   return hole_pos;
1005*6777b538SAndroid Build Coastguard Worker }
1006*6777b538SAndroid Build Coastguard Worker 
1007*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
1008*6777b538SAndroid Build Coastguard Worker template <typename FillElementType, typename U>
1009*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::size_type
MoveHoleDownAndFill(size_type hole_pos,U element)1010*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::MoveHoleDownAndFill(
1011*6777b538SAndroid Build Coastguard Worker     size_type hole_pos,
1012*6777b538SAndroid Build Coastguard Worker     U element) {
1013*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(hole_pos, size());
1014*6777b538SAndroid Build Coastguard Worker 
1015*6777b538SAndroid Build Coastguard Worker   // If we're filling with a leaf, then that leaf element is about to be erased.
1016*6777b538SAndroid Build Coastguard Worker   // We pretend that the space doesn't exist in the heap.
1017*6777b538SAndroid Build Coastguard Worker   const size_type n = size() - (FillElementType::kIsLeafElement ? 1 : 0);
1018*6777b538SAndroid Build Coastguard Worker 
1019*6777b538SAndroid Build Coastguard Worker   DCHECK_LT(hole_pos, n);
1020*6777b538SAndroid Build Coastguard Worker   DCHECK(!GetHeapHandle(hole_pos).IsValid());
1021*6777b538SAndroid Build Coastguard Worker 
1022*6777b538SAndroid Build Coastguard Worker   while (true) {
1023*6777b538SAndroid Build Coastguard Worker     // If this spot has no children, then we've gone down as far as we can go.
1024*6777b538SAndroid Build Coastguard Worker     size_type left = intrusive_heap::LeftIndex(hole_pos);
1025*6777b538SAndroid Build Coastguard Worker     if (left >= n)
1026*6777b538SAndroid Build Coastguard Worker       break;
1027*6777b538SAndroid Build Coastguard Worker     size_type right = left + 1;
1028*6777b538SAndroid Build Coastguard Worker 
1029*6777b538SAndroid Build Coastguard Worker     // Get the larger of the potentially two child nodes.
1030*6777b538SAndroid Build Coastguard Worker     size_type largest = left;
1031*6777b538SAndroid Build Coastguard Worker     if (right < n && Less(left, right))
1032*6777b538SAndroid Build Coastguard Worker       largest = right;
1033*6777b538SAndroid Build Coastguard Worker 
1034*6777b538SAndroid Build Coastguard Worker     // If we're not deterministically moving the element all the way down to
1035*6777b538SAndroid Build Coastguard Worker     // become a leaf, then stop when it is >= the largest of the children.
1036*6777b538SAndroid Build Coastguard Worker     if (!FillElementType::kIsLeafElement && !Less(element, largest))
1037*6777b538SAndroid Build Coastguard Worker       break;
1038*6777b538SAndroid Build Coastguard Worker 
1039*6777b538SAndroid Build Coastguard Worker     MoveHole(largest, hole_pos);
1040*6777b538SAndroid Build Coastguard Worker     hole_pos = largest;
1041*6777b538SAndroid Build Coastguard Worker   }
1042*6777b538SAndroid Build Coastguard Worker 
1043*6777b538SAndroid Build Coastguard Worker   if (FillElementType::kIsLeafElement) {
1044*6777b538SAndroid Build Coastguard Worker     // If we're filling with a leaf node we may need to bubble the leaf back up
1045*6777b538SAndroid Build Coastguard Worker     // the tree a bit to repair the heap.
1046*6777b538SAndroid Build Coastguard Worker     hole_pos = MoveHoleUpAndFill(hole_pos, std::move_if_noexcept(element));
1047*6777b538SAndroid Build Coastguard Worker   } else {
1048*6777b538SAndroid Build Coastguard Worker     FillHole(hole_pos, std::move_if_noexcept(element));
1049*6777b538SAndroid Build Coastguard Worker   }
1050*6777b538SAndroid Build Coastguard Worker   return hole_pos;
1051*6777b538SAndroid Build Coastguard Worker }
1052*6777b538SAndroid Build Coastguard Worker 
1053*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
1054*6777b538SAndroid Build Coastguard Worker template <typename U>
1055*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::const_iterator
InsertImpl(U element)1056*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::InsertImpl(U element) {
1057*6777b538SAndroid Build Coastguard Worker   // MoveHoleUpAndFill can tolerate the initial hole being in a slot that
1058*6777b538SAndroid Build Coastguard Worker   // doesn't yet exist. It will be created by MoveHole by copy/move, thus
1059*6777b538SAndroid Build Coastguard Worker   // removing the need for a default constructor.
1060*6777b538SAndroid Build Coastguard Worker   size_type i = MoveHoleUpAndFill(size(), std::move_if_noexcept(element));
1061*6777b538SAndroid Build Coastguard Worker   return cbegin() + static_cast<difference_type>(i);
1062*6777b538SAndroid Build Coastguard Worker }
1063*6777b538SAndroid Build Coastguard Worker 
1064*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
1065*6777b538SAndroid Build Coastguard Worker template <typename U>
1066*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::const_iterator
ReplaceImpl(size_type pos,U element)1067*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::ReplaceImpl(size_type pos,
1068*6777b538SAndroid Build Coastguard Worker                                                            U element) {
1069*6777b538SAndroid Build Coastguard Worker   // If we're greater than our parent we need to go up, otherwise we may need
1070*6777b538SAndroid Build Coastguard Worker   // to go down.
1071*6777b538SAndroid Build Coastguard Worker   MakeHole(pos);
1072*6777b538SAndroid Build Coastguard Worker   size_type i = 0;
1073*6777b538SAndroid Build Coastguard Worker   if (!Less(element, pos)) {
1074*6777b538SAndroid Build Coastguard Worker     i = MoveHoleUpAndFill(pos, std::move_if_noexcept(element));
1075*6777b538SAndroid Build Coastguard Worker   } else {
1076*6777b538SAndroid Build Coastguard Worker     i = MoveHoleDownAndFill<WithElement>(pos, std::move_if_noexcept(element));
1077*6777b538SAndroid Build Coastguard Worker   }
1078*6777b538SAndroid Build Coastguard Worker   return cbegin() + static_cast<difference_type>(i);
1079*6777b538SAndroid Build Coastguard Worker }
1080*6777b538SAndroid Build Coastguard Worker 
1081*6777b538SAndroid Build Coastguard Worker template <typename T, typename Compare, typename HeapHandleAccessor>
1082*6777b538SAndroid Build Coastguard Worker template <typename U>
1083*6777b538SAndroid Build Coastguard Worker typename IntrusiveHeap<T, Compare, HeapHandleAccessor>::const_iterator
ReplaceTopImpl(U element)1084*6777b538SAndroid Build Coastguard Worker IntrusiveHeap<T, Compare, HeapHandleAccessor>::ReplaceTopImpl(U element) {
1085*6777b538SAndroid Build Coastguard Worker   MakeHole(0u);
1086*6777b538SAndroid Build Coastguard Worker   size_type i =
1087*6777b538SAndroid Build Coastguard Worker       MoveHoleDownAndFill<WithElement>(0u, std::move_if_noexcept(element));
1088*6777b538SAndroid Build Coastguard Worker   return cbegin() + static_cast<difference_type>(i);
1089*6777b538SAndroid Build Coastguard Worker }
1090*6777b538SAndroid Build Coastguard Worker 
1091*6777b538SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
1092*6777b538SAndroid Build Coastguard Worker // WithHeapHandle
1093*6777b538SAndroid Build Coastguard Worker 
1094*6777b538SAndroid Build Coastguard Worker template <typename T>
1095*6777b538SAndroid Build Coastguard Worker template <class... Args>
WithHeapHandle(Args &&...args)1096*6777b538SAndroid Build Coastguard Worker WithHeapHandle<T>::WithHeapHandle(Args&&... args)
1097*6777b538SAndroid Build Coastguard Worker     : value_(std::forward<Args>(args)...) {}
1098*6777b538SAndroid Build Coastguard Worker 
1099*6777b538SAndroid Build Coastguard Worker template <typename T>
swap(WithHeapHandle & other)1100*6777b538SAndroid Build Coastguard Worker void WithHeapHandle<T>::swap(WithHeapHandle& other) noexcept {
1101*6777b538SAndroid Build Coastguard Worker   InternalHeapHandleStorage::swap(other);
1102*6777b538SAndroid Build Coastguard Worker   std::swap(value_, other.value_);
1103*6777b538SAndroid Build Coastguard Worker }
1104*6777b538SAndroid Build Coastguard Worker 
1105*6777b538SAndroid Build Coastguard Worker }  // namespace base
1106*6777b538SAndroid Build Coastguard Worker 
1107*6777b538SAndroid Build Coastguard Worker #endif  // BASE_CONTAINERS_INTRUSIVE_HEAP_H_
1108