xref: /aosp_15_r20/external/vixl/src/invalset-vixl.h (revision f5c631da2f1efdd72b5fd1e20510e4042af13d77)
1*f5c631daSSadaf Ebrahimi // Copyright 2015, VIXL authors
2*f5c631daSSadaf Ebrahimi // All rights reserved.
3*f5c631daSSadaf Ebrahimi //
4*f5c631daSSadaf Ebrahimi // Redistribution and use in source and binary forms, with or without
5*f5c631daSSadaf Ebrahimi // modification, are permitted provided that the following conditions are met:
6*f5c631daSSadaf Ebrahimi //
7*f5c631daSSadaf Ebrahimi //   * Redistributions of source code must retain the above copyright notice,
8*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer.
9*f5c631daSSadaf Ebrahimi //   * Redistributions in binary form must reproduce the above copyright notice,
10*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer in the documentation
11*f5c631daSSadaf Ebrahimi //     and/or other materials provided with the distribution.
12*f5c631daSSadaf Ebrahimi //   * Neither the name of ARM Limited nor the names of its contributors may be
13*f5c631daSSadaf Ebrahimi //     used to endorse or promote products derived from this software without
14*f5c631daSSadaf Ebrahimi //     specific prior written permission.
15*f5c631daSSadaf Ebrahimi //
16*f5c631daSSadaf Ebrahimi // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17*f5c631daSSadaf Ebrahimi // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*f5c631daSSadaf Ebrahimi // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*f5c631daSSadaf Ebrahimi // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20*f5c631daSSadaf Ebrahimi // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*f5c631daSSadaf Ebrahimi // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22*f5c631daSSadaf Ebrahimi // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23*f5c631daSSadaf Ebrahimi // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*f5c631daSSadaf Ebrahimi // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25*f5c631daSSadaf Ebrahimi // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*f5c631daSSadaf Ebrahimi 
27*f5c631daSSadaf Ebrahimi #ifndef VIXL_INVALSET_H_
28*f5c631daSSadaf Ebrahimi #define VIXL_INVALSET_H_
29*f5c631daSSadaf Ebrahimi 
30*f5c631daSSadaf Ebrahimi #include <cstring>
31*f5c631daSSadaf Ebrahimi 
32*f5c631daSSadaf Ebrahimi #include <algorithm>
33*f5c631daSSadaf Ebrahimi #include <vector>
34*f5c631daSSadaf Ebrahimi 
35*f5c631daSSadaf Ebrahimi #include "globals-vixl.h"
36*f5c631daSSadaf Ebrahimi 
37*f5c631daSSadaf Ebrahimi namespace vixl {
38*f5c631daSSadaf Ebrahimi 
39*f5c631daSSadaf Ebrahimi // We define a custom data structure template and its iterator as `std`
40*f5c631daSSadaf Ebrahimi // containers do not fit the performance requirements for some of our use cases.
41*f5c631daSSadaf Ebrahimi //
42*f5c631daSSadaf Ebrahimi // The structure behaves like an iterable unordered set with special properties
43*f5c631daSSadaf Ebrahimi // and restrictions. "InvalSet" stands for "Invalidatable Set".
44*f5c631daSSadaf Ebrahimi //
45*f5c631daSSadaf Ebrahimi // Restrictions and requirements:
46*f5c631daSSadaf Ebrahimi // - Adding an element already present in the set is illegal. In debug mode,
47*f5c631daSSadaf Ebrahimi //   this is checked at insertion time.
48*f5c631daSSadaf Ebrahimi // - The templated class `ElementType` must provide comparison operators so that
49*f5c631daSSadaf Ebrahimi //   `std::sort()` can be used.
50*f5c631daSSadaf Ebrahimi // - A key must be available to represent invalid elements.
51*f5c631daSSadaf Ebrahimi // - Elements with an invalid key must compare higher or equal to any other
52*f5c631daSSadaf Ebrahimi //   element.
53*f5c631daSSadaf Ebrahimi //
54*f5c631daSSadaf Ebrahimi // Use cases and performance considerations:
55*f5c631daSSadaf Ebrahimi // Our use cases present two specificities that allow us to design this
56*f5c631daSSadaf Ebrahimi // structure to provide fast insertion *and* fast search and deletion
57*f5c631daSSadaf Ebrahimi // operations:
58*f5c631daSSadaf Ebrahimi // - Elements are (generally) inserted in order (sorted according to their key).
59*f5c631daSSadaf Ebrahimi // - A key is available to mark elements as invalid (deleted).
60*f5c631daSSadaf Ebrahimi // The backing `std::vector` allows for fast insertions. When
61*f5c631daSSadaf Ebrahimi // searching for an element we ensure the elements are sorted (this is generally
62*f5c631daSSadaf Ebrahimi // the case) and perform a binary search. When deleting an element we do not
63*f5c631daSSadaf Ebrahimi // free the associated memory immediately. Instead, an element to be deleted is
64*f5c631daSSadaf Ebrahimi // marked with the 'invalid' key. Other methods of the container take care of
65*f5c631daSSadaf Ebrahimi // ignoring entries marked as invalid.
66*f5c631daSSadaf Ebrahimi // To avoid the overhead of the `std::vector` container when only few entries
67*f5c631daSSadaf Ebrahimi // are used, a number of elements are preallocated.
68*f5c631daSSadaf Ebrahimi 
69*f5c631daSSadaf Ebrahimi // 'ElementType' and 'KeyType' are respectively the types of the elements and
70*f5c631daSSadaf Ebrahimi // their key. The structure only reclaims memory when safe to do so, if the
71*f5c631daSSadaf Ebrahimi // number of elements that can be reclaimed is greater than `RECLAIM_FROM` and
72*f5c631daSSadaf Ebrahimi // greater than `<total number of elements> / RECLAIM_FACTOR.
73*f5c631daSSadaf Ebrahimi // clang-format off
74*f5c631daSSadaf Ebrahimi #define TEMPLATE_INVALSET_P_DECL                                               \
75*f5c631daSSadaf Ebrahimi   class ElementType,                                                           \
76*f5c631daSSadaf Ebrahimi   unsigned N_PREALLOCATED_ELEMENTS,                                            \
77*f5c631daSSadaf Ebrahimi   class KeyType,                                                               \
78*f5c631daSSadaf Ebrahimi   KeyType INVALID_KEY,                                                         \
79*f5c631daSSadaf Ebrahimi   size_t RECLAIM_FROM,                                                         \
80*f5c631daSSadaf Ebrahimi   unsigned RECLAIM_FACTOR
81*f5c631daSSadaf Ebrahimi // clang-format on
82*f5c631daSSadaf Ebrahimi 
83*f5c631daSSadaf Ebrahimi #define TEMPLATE_INVALSET_P_DEF                                             \
84*f5c631daSSadaf Ebrahimi   ElementType, N_PREALLOCATED_ELEMENTS, KeyType, INVALID_KEY, RECLAIM_FROM, \
85*f5c631daSSadaf Ebrahimi       RECLAIM_FACTOR
86*f5c631daSSadaf Ebrahimi 
87*f5c631daSSadaf Ebrahimi template <class S>
88*f5c631daSSadaf Ebrahimi class InvalSetIterator;  // Forward declaration.
89*f5c631daSSadaf Ebrahimi 
90*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
91*f5c631daSSadaf Ebrahimi class InvalSet {
92*f5c631daSSadaf Ebrahimi  public:
93*f5c631daSSadaf Ebrahimi   InvalSet();
94*f5c631daSSadaf Ebrahimi   ~InvalSet() VIXL_NEGATIVE_TESTING_ALLOW_EXCEPTION;
95*f5c631daSSadaf Ebrahimi 
96*f5c631daSSadaf Ebrahimi   static const size_t kNPreallocatedElements = N_PREALLOCATED_ELEMENTS;
97*f5c631daSSadaf Ebrahimi   static const KeyType kInvalidKey = INVALID_KEY;
98*f5c631daSSadaf Ebrahimi 
99*f5c631daSSadaf Ebrahimi   // C++ STL iterator interface.
100*f5c631daSSadaf Ebrahimi   typedef InvalSetIterator<InvalSet<TEMPLATE_INVALSET_P_DEF> > iterator;
101*f5c631daSSadaf Ebrahimi   iterator begin();
102*f5c631daSSadaf Ebrahimi   iterator end();
103*f5c631daSSadaf Ebrahimi 
104*f5c631daSSadaf Ebrahimi   // It is illegal to insert an element already present in the set.
105*f5c631daSSadaf Ebrahimi   void insert(const ElementType& element);
106*f5c631daSSadaf Ebrahimi 
107*f5c631daSSadaf Ebrahimi   // Looks for the specified element in the set and - if found - deletes it.
108*f5c631daSSadaf Ebrahimi   // The return value is the number of elements erased: either 0 or 1.
109*f5c631daSSadaf Ebrahimi   size_t erase(const ElementType& element);
110*f5c631daSSadaf Ebrahimi 
111*f5c631daSSadaf Ebrahimi   // This indicates the number of (valid) elements stored in this set.
112*f5c631daSSadaf Ebrahimi   size_t size() const;
113*f5c631daSSadaf Ebrahimi 
114*f5c631daSSadaf Ebrahimi   // Returns true if no elements are stored in the set.
115*f5c631daSSadaf Ebrahimi   // Note that this does not mean the the backing storage is empty: it can still
116*f5c631daSSadaf Ebrahimi   // contain invalid elements.
117*f5c631daSSadaf Ebrahimi   bool empty() const;
118*f5c631daSSadaf Ebrahimi 
119*f5c631daSSadaf Ebrahimi   void clear();
120*f5c631daSSadaf Ebrahimi 
121*f5c631daSSadaf Ebrahimi   const ElementType GetMinElement();
122*f5c631daSSadaf Ebrahimi 
123*f5c631daSSadaf Ebrahimi   // This returns the key of the minimum element in the set.
124*f5c631daSSadaf Ebrahimi   KeyType GetMinElementKey();
125*f5c631daSSadaf Ebrahimi 
126*f5c631daSSadaf Ebrahimi   static bool IsValid(const ElementType& element);
127*f5c631daSSadaf Ebrahimi   static KeyType GetKey(const ElementType& element);
128*f5c631daSSadaf Ebrahimi   static void SetKey(ElementType* element, KeyType key);
129*f5c631daSSadaf Ebrahimi 
130*f5c631daSSadaf Ebrahimi   typedef ElementType _ElementType;
131*f5c631daSSadaf Ebrahimi   typedef KeyType _KeyType;
132*f5c631daSSadaf Ebrahimi 
133*f5c631daSSadaf Ebrahimi  protected:
134*f5c631daSSadaf Ebrahimi   // Returns a pointer to the element in vector_ if it was found, or NULL
135*f5c631daSSadaf Ebrahimi   // otherwise.
136*f5c631daSSadaf Ebrahimi   ElementType* Search(const ElementType& element);
137*f5c631daSSadaf Ebrahimi 
138*f5c631daSSadaf Ebrahimi   // The argument *must* point to an element stored in *this* set.
139*f5c631daSSadaf Ebrahimi   // This function is not allowed to move elements in the backing vector
140*f5c631daSSadaf Ebrahimi   // storage.
141*f5c631daSSadaf Ebrahimi   void EraseInternal(ElementType* element);
142*f5c631daSSadaf Ebrahimi 
143*f5c631daSSadaf Ebrahimi   // The elements in the range searched must be sorted.
144*f5c631daSSadaf Ebrahimi   ElementType* BinarySearch(const ElementType& element,
145*f5c631daSSadaf Ebrahimi                             ElementType* start,
146*f5c631daSSadaf Ebrahimi                             ElementType* end) const;
147*f5c631daSSadaf Ebrahimi 
148*f5c631daSSadaf Ebrahimi   // Sort the elements.
149*f5c631daSSadaf Ebrahimi   enum SortType {
150*f5c631daSSadaf Ebrahimi     // The 'hard' version guarantees that invalid elements are moved to the end
151*f5c631daSSadaf Ebrahimi     // of the container.
152*f5c631daSSadaf Ebrahimi     kHardSort,
153*f5c631daSSadaf Ebrahimi     // The 'soft' version only guarantees that the elements will be sorted.
154*f5c631daSSadaf Ebrahimi     // Invalid elements may still be present anywhere in the set.
155*f5c631daSSadaf Ebrahimi     kSoftSort
156*f5c631daSSadaf Ebrahimi   };
157*f5c631daSSadaf Ebrahimi   void Sort(SortType sort_type);
158*f5c631daSSadaf Ebrahimi 
159*f5c631daSSadaf Ebrahimi   // Delete the elements that have an invalid key. The complexity is linear
160*f5c631daSSadaf Ebrahimi   // with the size of the vector.
161*f5c631daSSadaf Ebrahimi   void Clean();
162*f5c631daSSadaf Ebrahimi 
163*f5c631daSSadaf Ebrahimi   const ElementType Front() const;
164*f5c631daSSadaf Ebrahimi   const ElementType Back() const;
165*f5c631daSSadaf Ebrahimi 
166*f5c631daSSadaf Ebrahimi   // Delete invalid trailing elements and return the last valid element in the
167*f5c631daSSadaf Ebrahimi   // set.
168*f5c631daSSadaf Ebrahimi   const ElementType CleanBack();
169*f5c631daSSadaf Ebrahimi 
170*f5c631daSSadaf Ebrahimi   // Returns a pointer to the start or end of the backing storage.
171*f5c631daSSadaf Ebrahimi   const ElementType* StorageBegin() const;
172*f5c631daSSadaf Ebrahimi   const ElementType* StorageEnd() const;
173*f5c631daSSadaf Ebrahimi   ElementType* StorageBegin();
174*f5c631daSSadaf Ebrahimi   ElementType* StorageEnd();
175*f5c631daSSadaf Ebrahimi 
176*f5c631daSSadaf Ebrahimi   // Returns the index of the element within the backing storage. The element
177*f5c631daSSadaf Ebrahimi   // must belong to the backing storage.
178*f5c631daSSadaf Ebrahimi   size_t GetElementIndex(const ElementType* element) const;
179*f5c631daSSadaf Ebrahimi 
180*f5c631daSSadaf Ebrahimi   // Returns the element at the specified index in the backing storage.
181*f5c631daSSadaf Ebrahimi   const ElementType* GetElementAt(size_t index) const;
182*f5c631daSSadaf Ebrahimi   ElementType* GetElementAt(size_t index);
183*f5c631daSSadaf Ebrahimi 
184*f5c631daSSadaf Ebrahimi   static const ElementType* GetFirstValidElement(const ElementType* from,
185*f5c631daSSadaf Ebrahimi                                                  const ElementType* end);
186*f5c631daSSadaf Ebrahimi 
187*f5c631daSSadaf Ebrahimi   void CacheMinElement();
188*f5c631daSSadaf Ebrahimi   const ElementType GetCachedMinElement() const;
189*f5c631daSSadaf Ebrahimi 
190*f5c631daSSadaf Ebrahimi   bool ShouldReclaimMemory() const;
191*f5c631daSSadaf Ebrahimi   void ReclaimMemory();
192*f5c631daSSadaf Ebrahimi 
IsUsingVector()193*f5c631daSSadaf Ebrahimi   bool IsUsingVector() const { return vector_ != NULL; }
SetSorted(bool sorted)194*f5c631daSSadaf Ebrahimi   void SetSorted(bool sorted) { sorted_ = sorted; }
195*f5c631daSSadaf Ebrahimi 
196*f5c631daSSadaf Ebrahimi   // We cache some data commonly required by users to improve performance.
197*f5c631daSSadaf Ebrahimi   // We cannot cache pointers to elements as we do not control the backing
198*f5c631daSSadaf Ebrahimi   // storage.
199*f5c631daSSadaf Ebrahimi   bool valid_cached_min_;
200*f5c631daSSadaf Ebrahimi   size_t cached_min_index_;  // Valid iff `valid_cached_min_` is true.
201*f5c631daSSadaf Ebrahimi   KeyType cached_min_key_;   // Valid iff `valid_cached_min_` is true.
202*f5c631daSSadaf Ebrahimi 
203*f5c631daSSadaf Ebrahimi   // Indicates whether the elements are sorted.
204*f5c631daSSadaf Ebrahimi   bool sorted_;
205*f5c631daSSadaf Ebrahimi 
206*f5c631daSSadaf Ebrahimi   // This represents the number of (valid) elements in this set.
207*f5c631daSSadaf Ebrahimi   size_t size_;
208*f5c631daSSadaf Ebrahimi 
209*f5c631daSSadaf Ebrahimi   // The backing storage is either the array of preallocated elements or the
210*f5c631daSSadaf Ebrahimi   // vector. The structure starts by using the preallocated elements, and
211*f5c631daSSadaf Ebrahimi   // transitions (permanently) to using the vector once more than
212*f5c631daSSadaf Ebrahimi   // kNPreallocatedElements are used.
213*f5c631daSSadaf Ebrahimi   // Elements are only invalidated when using the vector. The preallocated
214*f5c631daSSadaf Ebrahimi   // storage always only contains valid elements.
215*f5c631daSSadaf Ebrahimi   ElementType preallocated_[kNPreallocatedElements];
216*f5c631daSSadaf Ebrahimi   std::vector<ElementType>* vector_;
217*f5c631daSSadaf Ebrahimi 
218*f5c631daSSadaf Ebrahimi   // Iterators acquire and release this monitor. While a set is acquired,
219*f5c631daSSadaf Ebrahimi   // certain operations are illegal to ensure that the iterator will
220*f5c631daSSadaf Ebrahimi   // correctly iterate over the elements in the set.
221*f5c631daSSadaf Ebrahimi   int monitor_;
222*f5c631daSSadaf Ebrahimi #ifdef VIXL_DEBUG
monitor()223*f5c631daSSadaf Ebrahimi   int monitor() const { return monitor_; }
Acquire()224*f5c631daSSadaf Ebrahimi   void Acquire() { monitor_++; }
Release()225*f5c631daSSadaf Ebrahimi   void Release() {
226*f5c631daSSadaf Ebrahimi     monitor_--;
227*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(monitor_ >= 0);
228*f5c631daSSadaf Ebrahimi   }
229*f5c631daSSadaf Ebrahimi #endif
230*f5c631daSSadaf Ebrahimi 
231*f5c631daSSadaf Ebrahimi  private:
232*f5c631daSSadaf Ebrahimi // The copy constructor and assignment operator are not used and the defaults
233*f5c631daSSadaf Ebrahimi // are unsafe, so disable them (without an implementation).
234*f5c631daSSadaf Ebrahimi #if __cplusplus >= 201103L
235*f5c631daSSadaf Ebrahimi   InvalSet(const InvalSet& other) = delete;
236*f5c631daSSadaf Ebrahimi   InvalSet operator=(const InvalSet& other) = delete;
237*f5c631daSSadaf Ebrahimi #else
238*f5c631daSSadaf Ebrahimi   InvalSet(const InvalSet& other);
239*f5c631daSSadaf Ebrahimi   InvalSet operator=(const InvalSet& other);
240*f5c631daSSadaf Ebrahimi #endif
241*f5c631daSSadaf Ebrahimi 
242*f5c631daSSadaf Ebrahimi   friend class InvalSetIterator<InvalSet<TEMPLATE_INVALSET_P_DEF> >;
243*f5c631daSSadaf Ebrahimi };
244*f5c631daSSadaf Ebrahimi 
245*f5c631daSSadaf Ebrahimi 
246*f5c631daSSadaf Ebrahimi template <class S>
247*f5c631daSSadaf Ebrahimi class InvalSetIterator : public std::iterator<std::forward_iterator_tag,
248*f5c631daSSadaf Ebrahimi                                               typename S::_ElementType> {
249*f5c631daSSadaf Ebrahimi  private:
250*f5c631daSSadaf Ebrahimi   // Redefine types to mirror the associated set types.
251*f5c631daSSadaf Ebrahimi   typedef typename S::_ElementType ElementType;
252*f5c631daSSadaf Ebrahimi   typedef typename S::_KeyType KeyType;
253*f5c631daSSadaf Ebrahimi 
254*f5c631daSSadaf Ebrahimi  public:
255*f5c631daSSadaf Ebrahimi   explicit InvalSetIterator(S* inval_set = NULL);
256*f5c631daSSadaf Ebrahimi 
257*f5c631daSSadaf Ebrahimi   // This class implements the standard copy-swap idiom.
258*f5c631daSSadaf Ebrahimi   ~InvalSetIterator();
259*f5c631daSSadaf Ebrahimi   InvalSetIterator(const InvalSetIterator<S>& other);
260*f5c631daSSadaf Ebrahimi   InvalSetIterator<S>& operator=(InvalSetIterator<S> other);
261*f5c631daSSadaf Ebrahimi #if __cplusplus >= 201103L
262*f5c631daSSadaf Ebrahimi   InvalSetIterator(InvalSetIterator<S>&& other) noexcept;
263*f5c631daSSadaf Ebrahimi #endif
264*f5c631daSSadaf Ebrahimi 
swap(InvalSetIterator<S> & a,InvalSetIterator<S> & b)265*f5c631daSSadaf Ebrahimi   friend void swap(InvalSetIterator<S>& a, InvalSetIterator<S>& b) {
266*f5c631daSSadaf Ebrahimi     using std::swap;
267*f5c631daSSadaf Ebrahimi     swap(a.using_vector_, b.using_vector_);
268*f5c631daSSadaf Ebrahimi     swap(a.index_, b.index_);
269*f5c631daSSadaf Ebrahimi     swap(a.inval_set_, b.inval_set_);
270*f5c631daSSadaf Ebrahimi   }
271*f5c631daSSadaf Ebrahimi 
272*f5c631daSSadaf Ebrahimi   // Return true if the iterator is at the end of the set.
273*f5c631daSSadaf Ebrahimi   bool Done() const;
274*f5c631daSSadaf Ebrahimi 
275*f5c631daSSadaf Ebrahimi   // Move this iterator to the end of the set.
276*f5c631daSSadaf Ebrahimi   void Finish();
277*f5c631daSSadaf Ebrahimi 
278*f5c631daSSadaf Ebrahimi   // Delete the current element and advance the iterator to point to the next
279*f5c631daSSadaf Ebrahimi   // element.
280*f5c631daSSadaf Ebrahimi   void DeleteCurrentAndAdvance();
281*f5c631daSSadaf Ebrahimi 
282*f5c631daSSadaf Ebrahimi   static bool IsValid(const ElementType& element);
283*f5c631daSSadaf Ebrahimi   static KeyType GetKey(const ElementType& element);
284*f5c631daSSadaf Ebrahimi 
285*f5c631daSSadaf Ebrahimi   // Extra helpers to support the forward-iterator interface.
286*f5c631daSSadaf Ebrahimi   InvalSetIterator<S>& operator++();    // Pre-increment.
287*f5c631daSSadaf Ebrahimi   InvalSetIterator<S> operator++(int);  // Post-increment.
288*f5c631daSSadaf Ebrahimi   bool operator==(const InvalSetIterator<S>& rhs) const;
289*f5c631daSSadaf Ebrahimi   bool operator!=(const InvalSetIterator<S>& rhs) const {
290*f5c631daSSadaf Ebrahimi     return !(*this == rhs);
291*f5c631daSSadaf Ebrahimi   }
292*f5c631daSSadaf Ebrahimi   ElementType& operator*() { return *Current(); }
293*f5c631daSSadaf Ebrahimi   const ElementType& operator*() const { return *Current(); }
294*f5c631daSSadaf Ebrahimi   ElementType* operator->() { return Current(); }
295*f5c631daSSadaf Ebrahimi   const ElementType* operator->() const { return Current(); }
296*f5c631daSSadaf Ebrahimi 
297*f5c631daSSadaf Ebrahimi  protected:
298*f5c631daSSadaf Ebrahimi   void MoveToValidElement();
299*f5c631daSSadaf Ebrahimi 
300*f5c631daSSadaf Ebrahimi   // Indicates if the iterator is looking at the vector or at the preallocated
301*f5c631daSSadaf Ebrahimi   // elements.
302*f5c631daSSadaf Ebrahimi   bool using_vector_;
303*f5c631daSSadaf Ebrahimi   // Used when looking at the preallocated elements, or in debug mode when using
304*f5c631daSSadaf Ebrahimi   // the vector to track how many times the iterator has advanced.
305*f5c631daSSadaf Ebrahimi   size_t index_;
306*f5c631daSSadaf Ebrahimi   typename std::vector<ElementType>::iterator iterator_;
307*f5c631daSSadaf Ebrahimi   S* inval_set_;
308*f5c631daSSadaf Ebrahimi 
309*f5c631daSSadaf Ebrahimi   // TODO: These helpers are deprecated and will be removed in future versions
310*f5c631daSSadaf Ebrahimi   // of VIXL.
311*f5c631daSSadaf Ebrahimi   ElementType* Current() const;
312*f5c631daSSadaf Ebrahimi   void Advance();
313*f5c631daSSadaf Ebrahimi };
314*f5c631daSSadaf Ebrahimi 
315*f5c631daSSadaf Ebrahimi 
316*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
InvalSet()317*f5c631daSSadaf Ebrahimi InvalSet<TEMPLATE_INVALSET_P_DEF>::InvalSet()
318*f5c631daSSadaf Ebrahimi     : valid_cached_min_(false), sorted_(true), size_(0), vector_(NULL) {
319*f5c631daSSadaf Ebrahimi #ifdef VIXL_DEBUG
320*f5c631daSSadaf Ebrahimi   monitor_ = 0;
321*f5c631daSSadaf Ebrahimi #endif
322*f5c631daSSadaf Ebrahimi }
323*f5c631daSSadaf Ebrahimi 
324*f5c631daSSadaf Ebrahimi 
325*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
~InvalSet()326*f5c631daSSadaf Ebrahimi InvalSet<TEMPLATE_INVALSET_P_DEF>::~InvalSet()
327*f5c631daSSadaf Ebrahimi     VIXL_NEGATIVE_TESTING_ALLOW_EXCEPTION {
328*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor_ == 0);
329*f5c631daSSadaf Ebrahimi   delete vector_;
330*f5c631daSSadaf Ebrahimi }
331*f5c631daSSadaf Ebrahimi 
332*f5c631daSSadaf Ebrahimi 
333*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
334*f5c631daSSadaf Ebrahimi typename InvalSet<TEMPLATE_INVALSET_P_DEF>::iterator
begin()335*f5c631daSSadaf Ebrahimi InvalSet<TEMPLATE_INVALSET_P_DEF>::begin() {
336*f5c631daSSadaf Ebrahimi   return iterator(this);
337*f5c631daSSadaf Ebrahimi }
338*f5c631daSSadaf Ebrahimi 
339*f5c631daSSadaf Ebrahimi 
340*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
341*f5c631daSSadaf Ebrahimi typename InvalSet<TEMPLATE_INVALSET_P_DEF>::iterator
end()342*f5c631daSSadaf Ebrahimi InvalSet<TEMPLATE_INVALSET_P_DEF>::end() {
343*f5c631daSSadaf Ebrahimi   iterator end(this);
344*f5c631daSSadaf Ebrahimi   end.Finish();
345*f5c631daSSadaf Ebrahimi   return end;
346*f5c631daSSadaf Ebrahimi }
347*f5c631daSSadaf Ebrahimi 
348*f5c631daSSadaf Ebrahimi 
349*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
insert(const ElementType & element)350*f5c631daSSadaf Ebrahimi void InvalSet<TEMPLATE_INVALSET_P_DEF>::insert(const ElementType& element) {
351*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
352*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(IsValid(element));
353*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(Search(element) == NULL);
354*f5c631daSSadaf Ebrahimi   SetSorted(empty() || (sorted_ && (element > CleanBack())));
355*f5c631daSSadaf Ebrahimi   if (IsUsingVector()) {
356*f5c631daSSadaf Ebrahimi     vector_->push_back(element);
357*f5c631daSSadaf Ebrahimi   } else {
358*f5c631daSSadaf Ebrahimi     if (size_ < kNPreallocatedElements) {
359*f5c631daSSadaf Ebrahimi       preallocated_[size_] = element;
360*f5c631daSSadaf Ebrahimi     } else {
361*f5c631daSSadaf Ebrahimi       // Transition to using the vector.
362*f5c631daSSadaf Ebrahimi       vector_ =
363*f5c631daSSadaf Ebrahimi           new std::vector<ElementType>(preallocated_, preallocated_ + size_);
364*f5c631daSSadaf Ebrahimi       vector_->push_back(element);
365*f5c631daSSadaf Ebrahimi     }
366*f5c631daSSadaf Ebrahimi   }
367*f5c631daSSadaf Ebrahimi   size_++;
368*f5c631daSSadaf Ebrahimi 
369*f5c631daSSadaf Ebrahimi   if (valid_cached_min_ && (element < GetMinElement())) {
370*f5c631daSSadaf Ebrahimi     cached_min_index_ = IsUsingVector() ? vector_->size() - 1 : size_ - 1;
371*f5c631daSSadaf Ebrahimi     cached_min_key_ = GetKey(element);
372*f5c631daSSadaf Ebrahimi     valid_cached_min_ = true;
373*f5c631daSSadaf Ebrahimi   }
374*f5c631daSSadaf Ebrahimi 
375*f5c631daSSadaf Ebrahimi   if (ShouldReclaimMemory()) {
376*f5c631daSSadaf Ebrahimi     ReclaimMemory();
377*f5c631daSSadaf Ebrahimi   }
378*f5c631daSSadaf Ebrahimi }
379*f5c631daSSadaf Ebrahimi 
380*f5c631daSSadaf Ebrahimi 
381*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
erase(const ElementType & element)382*f5c631daSSadaf Ebrahimi size_t InvalSet<TEMPLATE_INVALSET_P_DEF>::erase(const ElementType& element) {
383*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
384*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(IsValid(element));
385*f5c631daSSadaf Ebrahimi   ElementType* local_element = Search(element);
386*f5c631daSSadaf Ebrahimi   if (local_element != NULL) {
387*f5c631daSSadaf Ebrahimi     EraseInternal(local_element);
388*f5c631daSSadaf Ebrahimi     return 1;
389*f5c631daSSadaf Ebrahimi   }
390*f5c631daSSadaf Ebrahimi   return 0;
391*f5c631daSSadaf Ebrahimi }
392*f5c631daSSadaf Ebrahimi 
393*f5c631daSSadaf Ebrahimi 
394*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
Search(const ElementType & element)395*f5c631daSSadaf Ebrahimi ElementType* InvalSet<TEMPLATE_INVALSET_P_DEF>::Search(
396*f5c631daSSadaf Ebrahimi     const ElementType& element) {
397*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
398*f5c631daSSadaf Ebrahimi   if (empty()) {
399*f5c631daSSadaf Ebrahimi     return NULL;
400*f5c631daSSadaf Ebrahimi   }
401*f5c631daSSadaf Ebrahimi   if (ShouldReclaimMemory()) {
402*f5c631daSSadaf Ebrahimi     ReclaimMemory();
403*f5c631daSSadaf Ebrahimi   }
404*f5c631daSSadaf Ebrahimi   if (!sorted_) {
405*f5c631daSSadaf Ebrahimi     Sort(kHardSort);
406*f5c631daSSadaf Ebrahimi   }
407*f5c631daSSadaf Ebrahimi   if (!valid_cached_min_) {
408*f5c631daSSadaf Ebrahimi     CacheMinElement();
409*f5c631daSSadaf Ebrahimi   }
410*f5c631daSSadaf Ebrahimi   return BinarySearch(element, GetElementAt(cached_min_index_), StorageEnd());
411*f5c631daSSadaf Ebrahimi }
412*f5c631daSSadaf Ebrahimi 
413*f5c631daSSadaf Ebrahimi 
414*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
size()415*f5c631daSSadaf Ebrahimi size_t InvalSet<TEMPLATE_INVALSET_P_DEF>::size() const {
416*f5c631daSSadaf Ebrahimi   return size_;
417*f5c631daSSadaf Ebrahimi }
418*f5c631daSSadaf Ebrahimi 
419*f5c631daSSadaf Ebrahimi 
420*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
empty()421*f5c631daSSadaf Ebrahimi bool InvalSet<TEMPLATE_INVALSET_P_DEF>::empty() const {
422*f5c631daSSadaf Ebrahimi   return size_ == 0;
423*f5c631daSSadaf Ebrahimi }
424*f5c631daSSadaf Ebrahimi 
425*f5c631daSSadaf Ebrahimi 
426*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
clear()427*f5c631daSSadaf Ebrahimi void InvalSet<TEMPLATE_INVALSET_P_DEF>::clear() {
428*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
429*f5c631daSSadaf Ebrahimi   size_ = 0;
430*f5c631daSSadaf Ebrahimi   if (IsUsingVector()) {
431*f5c631daSSadaf Ebrahimi     vector_->clear();
432*f5c631daSSadaf Ebrahimi   }
433*f5c631daSSadaf Ebrahimi   SetSorted(true);
434*f5c631daSSadaf Ebrahimi   valid_cached_min_ = false;
435*f5c631daSSadaf Ebrahimi }
436*f5c631daSSadaf Ebrahimi 
437*f5c631daSSadaf Ebrahimi 
438*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
GetMinElement()439*f5c631daSSadaf Ebrahimi const ElementType InvalSet<TEMPLATE_INVALSET_P_DEF>::GetMinElement() {
440*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
441*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!empty());
442*f5c631daSSadaf Ebrahimi   CacheMinElement();
443*f5c631daSSadaf Ebrahimi   return *GetElementAt(cached_min_index_);
444*f5c631daSSadaf Ebrahimi }
445*f5c631daSSadaf Ebrahimi 
446*f5c631daSSadaf Ebrahimi 
447*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
GetMinElementKey()448*f5c631daSSadaf Ebrahimi KeyType InvalSet<TEMPLATE_INVALSET_P_DEF>::GetMinElementKey() {
449*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
450*f5c631daSSadaf Ebrahimi   if (valid_cached_min_) {
451*f5c631daSSadaf Ebrahimi     return cached_min_key_;
452*f5c631daSSadaf Ebrahimi   } else {
453*f5c631daSSadaf Ebrahimi     return GetKey(GetMinElement());
454*f5c631daSSadaf Ebrahimi   }
455*f5c631daSSadaf Ebrahimi }
456*f5c631daSSadaf Ebrahimi 
457*f5c631daSSadaf Ebrahimi 
458*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
IsValid(const ElementType & element)459*f5c631daSSadaf Ebrahimi bool InvalSet<TEMPLATE_INVALSET_P_DEF>::IsValid(const ElementType& element) {
460*f5c631daSSadaf Ebrahimi   return GetKey(element) != kInvalidKey;
461*f5c631daSSadaf Ebrahimi }
462*f5c631daSSadaf Ebrahimi 
463*f5c631daSSadaf Ebrahimi 
464*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
EraseInternal(ElementType * element)465*f5c631daSSadaf Ebrahimi void InvalSet<TEMPLATE_INVALSET_P_DEF>::EraseInternal(ElementType* element) {
466*f5c631daSSadaf Ebrahimi   // Note that this function must be safe even while an iterator has acquired
467*f5c631daSSadaf Ebrahimi   // this set.
468*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(element != NULL);
469*f5c631daSSadaf Ebrahimi   size_t deleted_index = GetElementIndex(element);
470*f5c631daSSadaf Ebrahimi   if (IsUsingVector()) {
471*f5c631daSSadaf Ebrahimi     VIXL_ASSERT((&(vector_->front()) <= element) &&
472*f5c631daSSadaf Ebrahimi                 (element <= &(vector_->back())));
473*f5c631daSSadaf Ebrahimi     SetKey(element, kInvalidKey);
474*f5c631daSSadaf Ebrahimi   } else {
475*f5c631daSSadaf Ebrahimi     VIXL_ASSERT((preallocated_ <= element) &&
476*f5c631daSSadaf Ebrahimi                 (element < (preallocated_ + kNPreallocatedElements)));
477*f5c631daSSadaf Ebrahimi     ElementType* end = preallocated_ + kNPreallocatedElements;
478*f5c631daSSadaf Ebrahimi     size_t copy_size = sizeof(*element) * (end - element - 1);
479*f5c631daSSadaf Ebrahimi     memmove(element, element + 1, copy_size);
480*f5c631daSSadaf Ebrahimi   }
481*f5c631daSSadaf Ebrahimi   size_--;
482*f5c631daSSadaf Ebrahimi 
483*f5c631daSSadaf Ebrahimi   if (valid_cached_min_ && (deleted_index == cached_min_index_)) {
484*f5c631daSSadaf Ebrahimi     if (sorted_ && !empty()) {
485*f5c631daSSadaf Ebrahimi       const ElementType* min = GetFirstValidElement(element, StorageEnd());
486*f5c631daSSadaf Ebrahimi       cached_min_index_ = GetElementIndex(min);
487*f5c631daSSadaf Ebrahimi       cached_min_key_ = GetKey(*min);
488*f5c631daSSadaf Ebrahimi       valid_cached_min_ = true;
489*f5c631daSSadaf Ebrahimi     } else {
490*f5c631daSSadaf Ebrahimi       valid_cached_min_ = false;
491*f5c631daSSadaf Ebrahimi     }
492*f5c631daSSadaf Ebrahimi   }
493*f5c631daSSadaf Ebrahimi }
494*f5c631daSSadaf Ebrahimi 
495*f5c631daSSadaf Ebrahimi 
496*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
BinarySearch(const ElementType & element,ElementType * start,ElementType * end)497*f5c631daSSadaf Ebrahimi ElementType* InvalSet<TEMPLATE_INVALSET_P_DEF>::BinarySearch(
498*f5c631daSSadaf Ebrahimi     const ElementType& element, ElementType* start, ElementType* end) const {
499*f5c631daSSadaf Ebrahimi   if (start == end) {
500*f5c631daSSadaf Ebrahimi     return NULL;
501*f5c631daSSadaf Ebrahimi   }
502*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(sorted_);
503*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(start < end);
504*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!empty());
505*f5c631daSSadaf Ebrahimi 
506*f5c631daSSadaf Ebrahimi   // Perform a binary search through the elements while ignoring invalid
507*f5c631daSSadaf Ebrahimi   // elements.
508*f5c631daSSadaf Ebrahimi   ElementType* elements = start;
509*f5c631daSSadaf Ebrahimi   size_t low = 0;
510*f5c631daSSadaf Ebrahimi   size_t high = (end - start) - 1;
511*f5c631daSSadaf Ebrahimi   while (low < high) {
512*f5c631daSSadaf Ebrahimi     // Find valid bounds.
513*f5c631daSSadaf Ebrahimi     while (!IsValid(elements[low]) && (low < high)) ++low;
514*f5c631daSSadaf Ebrahimi     while (!IsValid(elements[high]) && (low < high)) --high;
515*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(low <= high);
516*f5c631daSSadaf Ebrahimi     // Avoid overflow when computing the middle index.
517*f5c631daSSadaf Ebrahimi     size_t middle = low + (high - low) / 2;
518*f5c631daSSadaf Ebrahimi     if ((middle == low) || (middle == high)) {
519*f5c631daSSadaf Ebrahimi       break;
520*f5c631daSSadaf Ebrahimi     }
521*f5c631daSSadaf Ebrahimi     while ((middle < high - 1) && !IsValid(elements[middle])) ++middle;
522*f5c631daSSadaf Ebrahimi     while ((low + 1 < middle) && !IsValid(elements[middle])) --middle;
523*f5c631daSSadaf Ebrahimi     if (!IsValid(elements[middle])) {
524*f5c631daSSadaf Ebrahimi       break;
525*f5c631daSSadaf Ebrahimi     }
526*f5c631daSSadaf Ebrahimi     if (elements[middle] < element) {
527*f5c631daSSadaf Ebrahimi       low = middle;
528*f5c631daSSadaf Ebrahimi     } else {
529*f5c631daSSadaf Ebrahimi       high = middle;
530*f5c631daSSadaf Ebrahimi     }
531*f5c631daSSadaf Ebrahimi   }
532*f5c631daSSadaf Ebrahimi 
533*f5c631daSSadaf Ebrahimi   if (elements[low] == element) return &elements[low];
534*f5c631daSSadaf Ebrahimi   if (elements[high] == element) return &elements[high];
535*f5c631daSSadaf Ebrahimi   return NULL;
536*f5c631daSSadaf Ebrahimi }
537*f5c631daSSadaf Ebrahimi 
538*f5c631daSSadaf Ebrahimi 
539*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
Sort(SortType sort_type)540*f5c631daSSadaf Ebrahimi void InvalSet<TEMPLATE_INVALSET_P_DEF>::Sort(SortType sort_type) {
541*f5c631daSSadaf Ebrahimi   if (sort_type == kSoftSort) {
542*f5c631daSSadaf Ebrahimi     if (sorted_) {
543*f5c631daSSadaf Ebrahimi       return;
544*f5c631daSSadaf Ebrahimi     }
545*f5c631daSSadaf Ebrahimi   }
546*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
547*f5c631daSSadaf Ebrahimi   if (empty()) {
548*f5c631daSSadaf Ebrahimi     return;
549*f5c631daSSadaf Ebrahimi   }
550*f5c631daSSadaf Ebrahimi 
551*f5c631daSSadaf Ebrahimi   Clean();
552*f5c631daSSadaf Ebrahimi   std::sort(StorageBegin(), StorageEnd());
553*f5c631daSSadaf Ebrahimi 
554*f5c631daSSadaf Ebrahimi   SetSorted(true);
555*f5c631daSSadaf Ebrahimi   cached_min_index_ = 0;
556*f5c631daSSadaf Ebrahimi   cached_min_key_ = GetKey(Front());
557*f5c631daSSadaf Ebrahimi   valid_cached_min_ = true;
558*f5c631daSSadaf Ebrahimi }
559*f5c631daSSadaf Ebrahimi 
560*f5c631daSSadaf Ebrahimi 
561*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
Clean()562*f5c631daSSadaf Ebrahimi void InvalSet<TEMPLATE_INVALSET_P_DEF>::Clean() {
563*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
564*f5c631daSSadaf Ebrahimi   if (empty() || !IsUsingVector()) {
565*f5c631daSSadaf Ebrahimi     return;
566*f5c631daSSadaf Ebrahimi   }
567*f5c631daSSadaf Ebrahimi   // Manually iterate through the vector storage to discard invalid elements.
568*f5c631daSSadaf Ebrahimi   ElementType* start = &(vector_->front());
569*f5c631daSSadaf Ebrahimi   ElementType* end = start + vector_->size();
570*f5c631daSSadaf Ebrahimi   ElementType* c = start;
571*f5c631daSSadaf Ebrahimi   ElementType* first_invalid;
572*f5c631daSSadaf Ebrahimi   ElementType* first_valid;
573*f5c631daSSadaf Ebrahimi   ElementType* next_invalid;
574*f5c631daSSadaf Ebrahimi 
575*f5c631daSSadaf Ebrahimi   while ((c < end) && IsValid(*c)) c++;
576*f5c631daSSadaf Ebrahimi   first_invalid = c;
577*f5c631daSSadaf Ebrahimi 
578*f5c631daSSadaf Ebrahimi   while (c < end) {
579*f5c631daSSadaf Ebrahimi     while ((c < end) && !IsValid(*c)) c++;
580*f5c631daSSadaf Ebrahimi     first_valid = c;
581*f5c631daSSadaf Ebrahimi     while ((c < end) && IsValid(*c)) c++;
582*f5c631daSSadaf Ebrahimi     next_invalid = c;
583*f5c631daSSadaf Ebrahimi 
584*f5c631daSSadaf Ebrahimi     ptrdiff_t n_moved_elements = (next_invalid - first_valid);
585*f5c631daSSadaf Ebrahimi     memmove(first_invalid, first_valid, n_moved_elements * sizeof(*c));
586*f5c631daSSadaf Ebrahimi     first_invalid = first_invalid + n_moved_elements;
587*f5c631daSSadaf Ebrahimi     c = next_invalid;
588*f5c631daSSadaf Ebrahimi   }
589*f5c631daSSadaf Ebrahimi 
590*f5c631daSSadaf Ebrahimi   // Delete the trailing invalid elements.
591*f5c631daSSadaf Ebrahimi   vector_->erase(vector_->begin() + (first_invalid - start), vector_->end());
592*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(vector_->size() == size_);
593*f5c631daSSadaf Ebrahimi 
594*f5c631daSSadaf Ebrahimi   if (sorted_) {
595*f5c631daSSadaf Ebrahimi     valid_cached_min_ = true;
596*f5c631daSSadaf Ebrahimi     cached_min_index_ = 0;
597*f5c631daSSadaf Ebrahimi     cached_min_key_ = GetKey(*GetElementAt(0));
598*f5c631daSSadaf Ebrahimi   } else {
599*f5c631daSSadaf Ebrahimi     valid_cached_min_ = false;
600*f5c631daSSadaf Ebrahimi   }
601*f5c631daSSadaf Ebrahimi }
602*f5c631daSSadaf Ebrahimi 
603*f5c631daSSadaf Ebrahimi 
604*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
Front()605*f5c631daSSadaf Ebrahimi const ElementType InvalSet<TEMPLATE_INVALSET_P_DEF>::Front() const {
606*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!empty());
607*f5c631daSSadaf Ebrahimi   return IsUsingVector() ? vector_->front() : preallocated_[0];
608*f5c631daSSadaf Ebrahimi }
609*f5c631daSSadaf Ebrahimi 
610*f5c631daSSadaf Ebrahimi 
611*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
Back()612*f5c631daSSadaf Ebrahimi const ElementType InvalSet<TEMPLATE_INVALSET_P_DEF>::Back() const {
613*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!empty());
614*f5c631daSSadaf Ebrahimi   return IsUsingVector() ? vector_->back() : preallocated_[size_ - 1];
615*f5c631daSSadaf Ebrahimi }
616*f5c631daSSadaf Ebrahimi 
617*f5c631daSSadaf Ebrahimi 
618*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
CleanBack()619*f5c631daSSadaf Ebrahimi const ElementType InvalSet<TEMPLATE_INVALSET_P_DEF>::CleanBack() {
620*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
621*f5c631daSSadaf Ebrahimi   if (IsUsingVector()) {
622*f5c631daSSadaf Ebrahimi     // Delete the invalid trailing elements.
623*f5c631daSSadaf Ebrahimi     typename std::vector<ElementType>::reverse_iterator it = vector_->rbegin();
624*f5c631daSSadaf Ebrahimi     while (!IsValid(*it)) {
625*f5c631daSSadaf Ebrahimi       it++;
626*f5c631daSSadaf Ebrahimi     }
627*f5c631daSSadaf Ebrahimi     vector_->erase(it.base(), vector_->end());
628*f5c631daSSadaf Ebrahimi   }
629*f5c631daSSadaf Ebrahimi   return Back();
630*f5c631daSSadaf Ebrahimi }
631*f5c631daSSadaf Ebrahimi 
632*f5c631daSSadaf Ebrahimi 
633*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
StorageBegin()634*f5c631daSSadaf Ebrahimi const ElementType* InvalSet<TEMPLATE_INVALSET_P_DEF>::StorageBegin() const {
635*f5c631daSSadaf Ebrahimi   return IsUsingVector() ? &(vector_->front()) : preallocated_;
636*f5c631daSSadaf Ebrahimi }
637*f5c631daSSadaf Ebrahimi 
638*f5c631daSSadaf Ebrahimi 
639*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
StorageEnd()640*f5c631daSSadaf Ebrahimi const ElementType* InvalSet<TEMPLATE_INVALSET_P_DEF>::StorageEnd() const {
641*f5c631daSSadaf Ebrahimi   return IsUsingVector() ? &(vector_->back()) + 1 : preallocated_ + size_;
642*f5c631daSSadaf Ebrahimi }
643*f5c631daSSadaf Ebrahimi 
644*f5c631daSSadaf Ebrahimi 
645*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
StorageBegin()646*f5c631daSSadaf Ebrahimi ElementType* InvalSet<TEMPLATE_INVALSET_P_DEF>::StorageBegin() {
647*f5c631daSSadaf Ebrahimi   return IsUsingVector() ? &(vector_->front()) : preallocated_;
648*f5c631daSSadaf Ebrahimi }
649*f5c631daSSadaf Ebrahimi 
650*f5c631daSSadaf Ebrahimi 
651*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
StorageEnd()652*f5c631daSSadaf Ebrahimi ElementType* InvalSet<TEMPLATE_INVALSET_P_DEF>::StorageEnd() {
653*f5c631daSSadaf Ebrahimi   return IsUsingVector() ? &(vector_->back()) + 1 : preallocated_ + size_;
654*f5c631daSSadaf Ebrahimi }
655*f5c631daSSadaf Ebrahimi 
656*f5c631daSSadaf Ebrahimi 
657*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
GetElementIndex(const ElementType * element)658*f5c631daSSadaf Ebrahimi size_t InvalSet<TEMPLATE_INVALSET_P_DEF>::GetElementIndex(
659*f5c631daSSadaf Ebrahimi     const ElementType* element) const {
660*f5c631daSSadaf Ebrahimi   VIXL_ASSERT((StorageBegin() <= element) && (element < StorageEnd()));
661*f5c631daSSadaf Ebrahimi   return element - StorageBegin();
662*f5c631daSSadaf Ebrahimi }
663*f5c631daSSadaf Ebrahimi 
664*f5c631daSSadaf Ebrahimi 
665*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
GetElementAt(size_t index)666*f5c631daSSadaf Ebrahimi const ElementType* InvalSet<TEMPLATE_INVALSET_P_DEF>::GetElementAt(
667*f5c631daSSadaf Ebrahimi     size_t index) const {
668*f5c631daSSadaf Ebrahimi   VIXL_ASSERT((IsUsingVector() && (index < vector_->size())) ||
669*f5c631daSSadaf Ebrahimi               (index < size_));
670*f5c631daSSadaf Ebrahimi   return StorageBegin() + index;
671*f5c631daSSadaf Ebrahimi }
672*f5c631daSSadaf Ebrahimi 
673*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
GetElementAt(size_t index)674*f5c631daSSadaf Ebrahimi ElementType* InvalSet<TEMPLATE_INVALSET_P_DEF>::GetElementAt(size_t index) {
675*f5c631daSSadaf Ebrahimi   VIXL_ASSERT((IsUsingVector() && (index < vector_->size())) ||
676*f5c631daSSadaf Ebrahimi               (index < size_));
677*f5c631daSSadaf Ebrahimi   return StorageBegin() + index;
678*f5c631daSSadaf Ebrahimi }
679*f5c631daSSadaf Ebrahimi 
680*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
GetFirstValidElement(const ElementType * from,const ElementType * end)681*f5c631daSSadaf Ebrahimi const ElementType* InvalSet<TEMPLATE_INVALSET_P_DEF>::GetFirstValidElement(
682*f5c631daSSadaf Ebrahimi     const ElementType* from, const ElementType* end) {
683*f5c631daSSadaf Ebrahimi   while ((from < end) && !IsValid(*from)) {
684*f5c631daSSadaf Ebrahimi     from++;
685*f5c631daSSadaf Ebrahimi   }
686*f5c631daSSadaf Ebrahimi   return from;
687*f5c631daSSadaf Ebrahimi }
688*f5c631daSSadaf Ebrahimi 
689*f5c631daSSadaf Ebrahimi 
690*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
CacheMinElement()691*f5c631daSSadaf Ebrahimi void InvalSet<TEMPLATE_INVALSET_P_DEF>::CacheMinElement() {
692*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
693*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!empty());
694*f5c631daSSadaf Ebrahimi 
695*f5c631daSSadaf Ebrahimi   if (valid_cached_min_) {
696*f5c631daSSadaf Ebrahimi     return;
697*f5c631daSSadaf Ebrahimi   }
698*f5c631daSSadaf Ebrahimi 
699*f5c631daSSadaf Ebrahimi   if (sorted_) {
700*f5c631daSSadaf Ebrahimi     const ElementType* min = GetFirstValidElement(StorageBegin(), StorageEnd());
701*f5c631daSSadaf Ebrahimi     cached_min_index_ = GetElementIndex(min);
702*f5c631daSSadaf Ebrahimi     cached_min_key_ = GetKey(*min);
703*f5c631daSSadaf Ebrahimi     valid_cached_min_ = true;
704*f5c631daSSadaf Ebrahimi   } else {
705*f5c631daSSadaf Ebrahimi     Sort(kHardSort);
706*f5c631daSSadaf Ebrahimi   }
707*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(valid_cached_min_);
708*f5c631daSSadaf Ebrahimi }
709*f5c631daSSadaf Ebrahimi 
710*f5c631daSSadaf Ebrahimi 
711*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
ShouldReclaimMemory()712*f5c631daSSadaf Ebrahimi bool InvalSet<TEMPLATE_INVALSET_P_DEF>::ShouldReclaimMemory() const {
713*f5c631daSSadaf Ebrahimi   if (!IsUsingVector()) {
714*f5c631daSSadaf Ebrahimi     return false;
715*f5c631daSSadaf Ebrahimi   }
716*f5c631daSSadaf Ebrahimi   size_t n_invalid_elements = vector_->size() - size_;
717*f5c631daSSadaf Ebrahimi   return (n_invalid_elements > RECLAIM_FROM) &&
718*f5c631daSSadaf Ebrahimi          (n_invalid_elements > vector_->size() / RECLAIM_FACTOR);
719*f5c631daSSadaf Ebrahimi }
720*f5c631daSSadaf Ebrahimi 
721*f5c631daSSadaf Ebrahimi 
722*f5c631daSSadaf Ebrahimi template <TEMPLATE_INVALSET_P_DECL>
ReclaimMemory()723*f5c631daSSadaf Ebrahimi void InvalSet<TEMPLATE_INVALSET_P_DEF>::ReclaimMemory() {
724*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(monitor() == 0);
725*f5c631daSSadaf Ebrahimi   Clean();
726*f5c631daSSadaf Ebrahimi }
727*f5c631daSSadaf Ebrahimi 
728*f5c631daSSadaf Ebrahimi 
729*f5c631daSSadaf Ebrahimi template <class S>
InvalSetIterator(S * inval_set)730*f5c631daSSadaf Ebrahimi InvalSetIterator<S>::InvalSetIterator(S* inval_set)
731*f5c631daSSadaf Ebrahimi     : using_vector_((inval_set != NULL) && inval_set->IsUsingVector()),
732*f5c631daSSadaf Ebrahimi       index_(0),
733*f5c631daSSadaf Ebrahimi       inval_set_(inval_set) {
734*f5c631daSSadaf Ebrahimi   if (inval_set != NULL) {
735*f5c631daSSadaf Ebrahimi     inval_set->Sort(S::kSoftSort);
736*f5c631daSSadaf Ebrahimi #ifdef VIXL_DEBUG
737*f5c631daSSadaf Ebrahimi     inval_set->Acquire();
738*f5c631daSSadaf Ebrahimi #endif
739*f5c631daSSadaf Ebrahimi     if (using_vector_) {
740*f5c631daSSadaf Ebrahimi       iterator_ = typename std::vector<ElementType>::iterator(
741*f5c631daSSadaf Ebrahimi           inval_set_->vector_->begin());
742*f5c631daSSadaf Ebrahimi     }
743*f5c631daSSadaf Ebrahimi     MoveToValidElement();
744*f5c631daSSadaf Ebrahimi   }
745*f5c631daSSadaf Ebrahimi }
746*f5c631daSSadaf Ebrahimi 
747*f5c631daSSadaf Ebrahimi 
748*f5c631daSSadaf Ebrahimi template <class S>
~InvalSetIterator()749*f5c631daSSadaf Ebrahimi InvalSetIterator<S>::~InvalSetIterator() {
750*f5c631daSSadaf Ebrahimi #ifdef VIXL_DEBUG
751*f5c631daSSadaf Ebrahimi   if (inval_set_ != NULL) inval_set_->Release();
752*f5c631daSSadaf Ebrahimi #endif
753*f5c631daSSadaf Ebrahimi }
754*f5c631daSSadaf Ebrahimi 
755*f5c631daSSadaf Ebrahimi 
756*f5c631daSSadaf Ebrahimi template <class S>
Current()757*f5c631daSSadaf Ebrahimi typename S::_ElementType* InvalSetIterator<S>::Current() const {
758*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!Done());
759*f5c631daSSadaf Ebrahimi   if (using_vector_) {
760*f5c631daSSadaf Ebrahimi     return &(*iterator_);
761*f5c631daSSadaf Ebrahimi   } else {
762*f5c631daSSadaf Ebrahimi     return &(inval_set_->preallocated_[index_]);
763*f5c631daSSadaf Ebrahimi   }
764*f5c631daSSadaf Ebrahimi }
765*f5c631daSSadaf Ebrahimi 
766*f5c631daSSadaf Ebrahimi 
767*f5c631daSSadaf Ebrahimi template <class S>
Advance()768*f5c631daSSadaf Ebrahimi void InvalSetIterator<S>::Advance() {
769*f5c631daSSadaf Ebrahimi   ++(*this);
770*f5c631daSSadaf Ebrahimi }
771*f5c631daSSadaf Ebrahimi 
772*f5c631daSSadaf Ebrahimi 
773*f5c631daSSadaf Ebrahimi template <class S>
Done()774*f5c631daSSadaf Ebrahimi bool InvalSetIterator<S>::Done() const {
775*f5c631daSSadaf Ebrahimi   if (using_vector_) {
776*f5c631daSSadaf Ebrahimi     bool done = (iterator_ == inval_set_->vector_->end());
777*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(done == (index_ == inval_set_->size()));
778*f5c631daSSadaf Ebrahimi     return done;
779*f5c631daSSadaf Ebrahimi   } else {
780*f5c631daSSadaf Ebrahimi     return index_ == inval_set_->size();
781*f5c631daSSadaf Ebrahimi   }
782*f5c631daSSadaf Ebrahimi }
783*f5c631daSSadaf Ebrahimi 
784*f5c631daSSadaf Ebrahimi 
785*f5c631daSSadaf Ebrahimi template <class S>
Finish()786*f5c631daSSadaf Ebrahimi void InvalSetIterator<S>::Finish() {
787*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(inval_set_->sorted_);
788*f5c631daSSadaf Ebrahimi   if (using_vector_) {
789*f5c631daSSadaf Ebrahimi     iterator_ = inval_set_->vector_->end();
790*f5c631daSSadaf Ebrahimi   }
791*f5c631daSSadaf Ebrahimi   index_ = inval_set_->size();
792*f5c631daSSadaf Ebrahimi }
793*f5c631daSSadaf Ebrahimi 
794*f5c631daSSadaf Ebrahimi 
795*f5c631daSSadaf Ebrahimi template <class S>
DeleteCurrentAndAdvance()796*f5c631daSSadaf Ebrahimi void InvalSetIterator<S>::DeleteCurrentAndAdvance() {
797*f5c631daSSadaf Ebrahimi   if (using_vector_) {
798*f5c631daSSadaf Ebrahimi     inval_set_->EraseInternal(&(*iterator_));
799*f5c631daSSadaf Ebrahimi     MoveToValidElement();
800*f5c631daSSadaf Ebrahimi   } else {
801*f5c631daSSadaf Ebrahimi     inval_set_->EraseInternal(inval_set_->preallocated_ + index_);
802*f5c631daSSadaf Ebrahimi   }
803*f5c631daSSadaf Ebrahimi }
804*f5c631daSSadaf Ebrahimi 
805*f5c631daSSadaf Ebrahimi 
806*f5c631daSSadaf Ebrahimi template <class S>
IsValid(const ElementType & element)807*f5c631daSSadaf Ebrahimi bool InvalSetIterator<S>::IsValid(const ElementType& element) {
808*f5c631daSSadaf Ebrahimi   return S::IsValid(element);
809*f5c631daSSadaf Ebrahimi }
810*f5c631daSSadaf Ebrahimi 
811*f5c631daSSadaf Ebrahimi 
812*f5c631daSSadaf Ebrahimi template <class S>
GetKey(const ElementType & element)813*f5c631daSSadaf Ebrahimi typename S::_KeyType InvalSetIterator<S>::GetKey(const ElementType& element) {
814*f5c631daSSadaf Ebrahimi   return S::GetKey(element);
815*f5c631daSSadaf Ebrahimi }
816*f5c631daSSadaf Ebrahimi 
817*f5c631daSSadaf Ebrahimi 
818*f5c631daSSadaf Ebrahimi template <class S>
MoveToValidElement()819*f5c631daSSadaf Ebrahimi void InvalSetIterator<S>::MoveToValidElement() {
820*f5c631daSSadaf Ebrahimi   if (using_vector_) {
821*f5c631daSSadaf Ebrahimi     while ((iterator_ != inval_set_->vector_->end()) && !IsValid(*iterator_)) {
822*f5c631daSSadaf Ebrahimi       iterator_++;
823*f5c631daSSadaf Ebrahimi     }
824*f5c631daSSadaf Ebrahimi   } else {
825*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(inval_set_->empty() || IsValid(inval_set_->preallocated_[0]));
826*f5c631daSSadaf Ebrahimi     // Nothing to do.
827*f5c631daSSadaf Ebrahimi   }
828*f5c631daSSadaf Ebrahimi }
829*f5c631daSSadaf Ebrahimi 
830*f5c631daSSadaf Ebrahimi 
831*f5c631daSSadaf Ebrahimi template <class S>
InvalSetIterator(const InvalSetIterator<S> & other)832*f5c631daSSadaf Ebrahimi InvalSetIterator<S>::InvalSetIterator(const InvalSetIterator<S>& other)
833*f5c631daSSadaf Ebrahimi     : using_vector_(other.using_vector_),
834*f5c631daSSadaf Ebrahimi       index_(other.index_),
835*f5c631daSSadaf Ebrahimi       inval_set_(other.inval_set_) {
836*f5c631daSSadaf Ebrahimi #ifdef VIXL_DEBUG
837*f5c631daSSadaf Ebrahimi   if (inval_set_ != NULL) inval_set_->Acquire();
838*f5c631daSSadaf Ebrahimi #endif
839*f5c631daSSadaf Ebrahimi }
840*f5c631daSSadaf Ebrahimi 
841*f5c631daSSadaf Ebrahimi 
842*f5c631daSSadaf Ebrahimi #if __cplusplus >= 201103L
843*f5c631daSSadaf Ebrahimi template <class S>
InvalSetIterator(InvalSetIterator<S> && other)844*f5c631daSSadaf Ebrahimi InvalSetIterator<S>::InvalSetIterator(InvalSetIterator<S>&& other) noexcept
845*f5c631daSSadaf Ebrahimi     : using_vector_(false), index_(0), inval_set_(NULL) {
846*f5c631daSSadaf Ebrahimi   swap(*this, other);
847*f5c631daSSadaf Ebrahimi }
848*f5c631daSSadaf Ebrahimi #endif
849*f5c631daSSadaf Ebrahimi 
850*f5c631daSSadaf Ebrahimi 
851*f5c631daSSadaf Ebrahimi template <class S>
852*f5c631daSSadaf Ebrahimi InvalSetIterator<S>& InvalSetIterator<S>::operator=(InvalSetIterator<S> other) {
853*f5c631daSSadaf Ebrahimi   swap(*this, other);
854*f5c631daSSadaf Ebrahimi   return *this;
855*f5c631daSSadaf Ebrahimi }
856*f5c631daSSadaf Ebrahimi 
857*f5c631daSSadaf Ebrahimi 
858*f5c631daSSadaf Ebrahimi template <class S>
859*f5c631daSSadaf Ebrahimi bool InvalSetIterator<S>::operator==(const InvalSetIterator<S>& rhs) const {
860*f5c631daSSadaf Ebrahimi   bool equal = (inval_set_ == rhs.inval_set_);
861*f5c631daSSadaf Ebrahimi 
862*f5c631daSSadaf Ebrahimi   // If the inval_set_ matches, using_vector_ must also match.
863*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!equal || (using_vector_ == rhs.using_vector_));
864*f5c631daSSadaf Ebrahimi 
865*f5c631daSSadaf Ebrahimi   if (using_vector_) {
866*f5c631daSSadaf Ebrahimi     equal = equal && (iterator_ == rhs.iterator_);
867*f5c631daSSadaf Ebrahimi     // In debug mode, index_ is maintained even with using_vector_.
868*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(!equal || (index_ == rhs.index_));
869*f5c631daSSadaf Ebrahimi   } else {
870*f5c631daSSadaf Ebrahimi     equal = equal && (index_ == rhs.index_);
871*f5c631daSSadaf Ebrahimi #ifdef DEBUG
872*f5c631daSSadaf Ebrahimi     // If not using_vector_, iterator_ should be default-initialised.
873*f5c631daSSadaf Ebrahimi     typename std::vector<ElementType>::iterator default_iterator;
874*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(iterator_ == default_iterator);
875*f5c631daSSadaf Ebrahimi     VIXL_ASSERT(rhs.iterator_ == default_iterator);
876*f5c631daSSadaf Ebrahimi #endif
877*f5c631daSSadaf Ebrahimi   }
878*f5c631daSSadaf Ebrahimi   return equal;
879*f5c631daSSadaf Ebrahimi }
880*f5c631daSSadaf Ebrahimi 
881*f5c631daSSadaf Ebrahimi 
882*f5c631daSSadaf Ebrahimi template <class S>
883*f5c631daSSadaf Ebrahimi InvalSetIterator<S>& InvalSetIterator<S>::operator++() {
884*f5c631daSSadaf Ebrahimi   // Pre-increment.
885*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!Done());
886*f5c631daSSadaf Ebrahimi   if (using_vector_) {
887*f5c631daSSadaf Ebrahimi     iterator_++;
888*f5c631daSSadaf Ebrahimi #ifdef VIXL_DEBUG
889*f5c631daSSadaf Ebrahimi     index_++;
890*f5c631daSSadaf Ebrahimi #endif
891*f5c631daSSadaf Ebrahimi     MoveToValidElement();
892*f5c631daSSadaf Ebrahimi   } else {
893*f5c631daSSadaf Ebrahimi     index_++;
894*f5c631daSSadaf Ebrahimi   }
895*f5c631daSSadaf Ebrahimi   return *this;
896*f5c631daSSadaf Ebrahimi }
897*f5c631daSSadaf Ebrahimi 
898*f5c631daSSadaf Ebrahimi 
899*f5c631daSSadaf Ebrahimi template <class S>
900*f5c631daSSadaf Ebrahimi InvalSetIterator<S> InvalSetIterator<S>::operator++(int /* unused */) {
901*f5c631daSSadaf Ebrahimi   // Post-increment.
902*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(!Done());
903*f5c631daSSadaf Ebrahimi   InvalSetIterator<S> old(*this);
904*f5c631daSSadaf Ebrahimi   ++(*this);
905*f5c631daSSadaf Ebrahimi   return old;
906*f5c631daSSadaf Ebrahimi }
907*f5c631daSSadaf Ebrahimi 
908*f5c631daSSadaf Ebrahimi 
909*f5c631daSSadaf Ebrahimi #undef TEMPLATE_INVALSET_P_DECL
910*f5c631daSSadaf Ebrahimi #undef TEMPLATE_INVALSET_P_DEF
911*f5c631daSSadaf Ebrahimi 
912*f5c631daSSadaf Ebrahimi }  // namespace vixl
913*f5c631daSSadaf Ebrahimi 
914*f5c631daSSadaf Ebrahimi #endif  // VIXL_INVALSET_H_
915