abseil-cpp/absl/container/internal/raw_hash_set.h
Go to the documentation of this file.
1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // An open-addressing
16 // hashtable with quadratic probing.
17 //
18 // This is a low level hashtable on top of which different interfaces can be
19 // implemented, like flat_hash_set, node_hash_set, string_hash_set, etc.
20 //
21 // The table interface is similar to that of std::unordered_set. Notable
22 // differences are that most member functions support heterogeneous keys when
23 // BOTH the hash and eq functions are marked as transparent. They do so by
24 // providing a typedef called `is_transparent`.
25 //
26 // When heterogeneous lookup is enabled, functions that take key_type act as if
27 // they have an overload set like:
28 //
29 // iterator find(const key_type& key);
30 // template <class K>
31 // iterator find(const K& key);
32 //
33 // size_type erase(const key_type& key);
34 // template <class K>
35 // size_type erase(const K& key);
36 //
37 // std::pair<iterator, iterator> equal_range(const key_type& key);
38 // template <class K>
39 // std::pair<iterator, iterator> equal_range(const K& key);
40 //
41 // When heterogeneous lookup is disabled, only the explicit `key_type` overloads
42 // exist.
43 //
44 // find() also supports passing the hash explicitly:
45 //
46 // iterator find(const key_type& key, size_t hash);
47 // template <class U>
48 // iterator find(const U& key, size_t hash);
49 //
50 // In addition the pointer to element and iterator stability guarantees are
51 // weaker: all iterators and pointers are invalidated after a new element is
52 // inserted.
53 //
54 // IMPLEMENTATION DETAILS
55 //
56 // # Table Layout
57 //
58 // A raw_hash_set's backing array consists of control bytes followed by slots
59 // that may or may not contain objects.
60 //
61 // The layout of the backing array, for `capacity` slots, is thus, as a
62 // pseudo-struct:
63 //
64 // struct BackingArray {
65 // // Control bytes for the "real" slots.
66 // ctrl_t ctrl[capacity];
67 // // Always `ctrl_t::kSentinel`. This is used by iterators to find when to
68 // // stop and serves no other purpose.
69 // ctrl_t sentinel;
70 // // A copy of the first `kWidth - 1` elements of `ctrl`. This is used so
71 // // that if a probe sequence picks a value near the end of `ctrl`,
72 // // `Group` will have valid control bytes to look at.
73 // ctrl_t clones[kWidth - 1];
74 // // The actual slot data.
75 // slot_type slots[capacity];
76 // };
77 //
78 // The length of this array is computed by `AllocSize()` below.
79 //
80 // Control bytes (`ctrl_t`) are bytes (collected into groups of a
81 // platform-specific size) that define the state of the corresponding slot in
82 // the slot array. Group manipulation is tightly optimized to be as efficient
83 // as possible: SSE and friends on x86, clever bit operations on other arches.
84 //
85 // Group 1 Group 2 Group 3
86 // +---------------+---------------+---------------+
87 // | | | | | | | | | | | | | | | | | | | | | | | | |
88 // +---------------+---------------+---------------+
89 //
90 // Each control byte is either a special value for empty slots, deleted slots
91 // (sometimes called *tombstones*), and a special end-of-table marker used by
92 // iterators, or, if occupied, seven bits (H2) from the hash of the value in the
93 // corresponding slot.
94 //
95 // Storing control bytes in a separate array also has beneficial cache effects,
96 // since more logical slots will fit into a cache line.
97 //
98 // # Hashing
99 //
100 // We compute two separate hashes, `H1` and `H2`, from the hash of an object.
101 // `H1(hash(x))` is an index into `slots`, and essentially the starting point
102 // for the probe sequence. `H2(hash(x))` is a 7-bit value used to filter out
103 // objects that cannot possibly be the one we are looking for.
104 //
105 // # Table operations.
106 //
107 // The key operations are `insert`, `find`, and `erase`.
108 //
109 // Since `insert` and `erase` are implemented in terms of `find`, we describe
110 // `find` first. To `find` a value `x`, we compute `hash(x)`. From
111 // `H1(hash(x))` and the capacity, we construct a `probe_seq` that visits every
112 // group of slots in some interesting order.
113 //
114 // We now walk through these indices. At each index, we select the entire group
115 // starting with that index and extract potential candidates: occupied slots
116 // with a control byte equal to `H2(hash(x))`. If we find an empty slot in the
117 // group, we stop and return an error. Each candidate slot `y` is compared with
118 // `x`; if `x == y`, we are done and return `&y`; otherwise we contine to the
119 // next probe index. Tombstones effectively behave like full slots that never
120 // match the value we're looking for.
121 //
122 // The `H2` bits ensure when we compare a slot to an object with `==`, we are
123 // likely to have actually found the object. That is, the chance is low that
124 // `==` is called and returns `false`. Thus, when we search for an object, we
125 // are unlikely to call `==` many times. This likelyhood can be analyzed as
126 // follows (assuming that H2 is a random enough hash function).
127 //
128 // Let's assume that there are `k` "wrong" objects that must be examined in a
129 // probe sequence. For example, when doing a `find` on an object that is in the
130 // table, `k` is the number of objects between the start of the probe sequence
131 // and the final found object (not including the final found object). The
132 // expected number of objects with an H2 match is then `k/128`. Measurements
133 // and analysis indicate that even at high load factors, `k` is less than 32,
134 // meaning that the number of "false positive" comparisons we must perform is
135 // less than 1/8 per `find`.
136 
137 // `insert` is implemented in terms of `unchecked_insert`, which inserts a
138 // value presumed to not be in the table (violating this requirement will cause
139 // the table to behave erratically). Given `x` and its hash `hash(x)`, to insert
140 // it, we construct a `probe_seq` once again, and use it to find the first
141 // group with an unoccupied (empty *or* deleted) slot. We place `x` into the
142 // first such slot in the group and mark it as full with `x`'s H2.
143 //
144 // To `insert`, we compose `unchecked_insert` with `find`. We compute `h(x)` and
145 // perform a `find` to see if it's already present; if it is, we're done. If
146 // it's not, we may decide the table is getting overcrowded (i.e. the load
147 // factor is greater than 7/8 for big tables; `is_small()` tables use a max load
148 // factor of 1); in this case, we allocate a bigger array, `unchecked_insert`
149 // each element of the table into the new array (we know that no insertion here
150 // will insert an already-present value), and discard the old backing array. At
151 // this point, we may `unchecked_insert` the value `x`.
152 //
153 // Below, `unchecked_insert` is partly implemented by `prepare_insert`, which
154 // presents a viable, initialized slot pointee to the caller.
155 //
156 // `erase` is implemented in terms of `erase_at`, which takes an index to a
157 // slot. Given an offset, we simply create a tombstone and destroy its contents.
158 // If we can prove that the slot would not appear in a probe sequence, we can
159 // make the slot as empty, instead. We can prove this by observing that if a
160 // group has any empty slots, it has never been full (assuming we never create
161 // an empty slot in a group with no empties, which this heuristic guarantees we
162 // never do) and find would stop at this group anyways (since it does not probe
163 // beyond groups with empties).
164 //
165 // `erase` is `erase_at` composed with `find`: if we
166 // have a value `x`, we can perform a `find`, and then `erase_at` the resulting
167 // slot.
168 //
169 // To iterate, we simply traverse the array, skipping empty and deleted slots
170 // and stopping when we hit a `kSentinel`.
171 
172 #ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
173 #define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
174 
175 #include <algorithm>
176 #include <cmath>
177 #include <cstdint>
178 #include <cstring>
179 #include <iterator>
180 #include <limits>
181 #include <memory>
182 #include <tuple>
183 #include <type_traits>
184 #include <utility>
185 
186 #include "absl/base/config.h"
187 #include "absl/base/internal/endian.h"
189 #include "absl/base/optimization.h"
190 #include "absl/base/port.h"
191 #include "absl/container/internal/common.h"
192 #include "absl/container/internal/compressed_tuple.h"
193 #include "absl/container/internal/container_memory.h"
194 #include "absl/container/internal/hash_policy_traits.h"
195 #include "absl/container/internal/hashtable_debug_hooks.h"
196 #include "absl/container/internal/hashtablez_sampler.h"
197 #include "absl/memory/memory.h"
198 #include "absl/meta/type_traits.h"
199 #include "absl/numeric/bits.h"
200 #include "absl/utility/utility.h"
201 
202 #ifdef ABSL_INTERNAL_HAVE_SSE2
203 #include <emmintrin.h>
204 #endif
205 
206 #ifdef ABSL_INTERNAL_HAVE_SSSE3
207 #include <tmmintrin.h>
208 #endif
209 
210 #ifdef _MSC_VER
211 #include <intrin.h>
212 #endif
213 
214 #ifdef ABSL_INTERNAL_HAVE_ARM_NEON
215 #include <arm_neon.h>
216 #endif
217 
218 namespace absl {
220 namespace container_internal {
221 
222 template <typename AllocType>
223 void SwapAlloc(AllocType& lhs, AllocType& rhs,
224  std::true_type /* propagate_on_container_swap */) {
225  using std::swap;
226  swap(lhs, rhs);
227 }
228 template <typename AllocType>
229 void SwapAlloc(AllocType& /*lhs*/, AllocType& /*rhs*/,
230  std::false_type /* propagate_on_container_swap */) {}
231 
232 // The state for a probe sequence.
233 //
234 // Currently, the sequence is a triangular progression of the form
235 //
236 // p(i) := Width * (i^2 + i)/2 + hash (mod mask + 1)
237 //
238 // The use of `Width` ensures that each probe step does not overlap groups;
239 // the sequence effectively outputs the addresses of *groups* (although not
240 // necessarily aligned to any boundary). The `Group` machinery allows us
241 // to check an entire group with minimal branching.
242 //
243 // Wrapping around at `mask + 1` is important, but not for the obvious reason.
244 // As described above, the first few entries of the control byte array
245 // are mirrored at the end of the array, which `Group` will find and use
246 // for selecting candidates. However, when those candidates' slots are
247 // actually inspected, there are no corresponding slots for the cloned bytes,
248 // so we need to make sure we've treated those offsets as "wrapping around".
249 //
250 // It turns out that this probe sequence visits every group exactly once if the
251 // number of groups is a power of two, since (i^2+i)/2 is a bijection in
252 // Z/(2^m). See https://en.wikipedia.org/wiki/Quadratic_probing
253 template <size_t Width>
254 class probe_seq {
255  public:
256  // Creates a new probe sequence using `hash` as the initial value of the
257  // sequence and `mask` (usually the capacity of the table) as the mask to
258  // apply to each value in the progression.
259  probe_seq(size_t hash, size_t mask) {
260  assert(((mask + 1) & mask) == 0 && "not a mask");
261  mask_ = mask;
262  offset_ = hash & mask_;
263  }
264 
265  // The offset within the table, i.e., the value `p(i)` above.
266  size_t offset() const { return offset_; }
267  size_t offset(size_t i) const { return (offset_ + i) & mask_; }
268 
269  void next() {
270  index_ += Width;
271  offset_ += index_;
272  offset_ &= mask_;
273  }
274  // 0-based probe index, a multiple of `Width`.
275  size_t index() const { return index_; }
276 
277  private:
278  size_t mask_;
279  size_t offset_;
280  size_t index_ = 0;
281 };
282 
283 template <class ContainerKey, class Hash, class Eq>
285  template <class PassedKey, class... Args>
286  std::pair<
287  decltype(std::declval<const Hash&>()(std::declval<const PassedKey&>())),
288  decltype(std::declval<const Eq&>()(std::declval<const ContainerKey&>(),
289  std::declval<const PassedKey&>()))>*
290  operator()(const PassedKey&, const Args&...) const;
291 };
292 
293 template <class E, class Policy, class Hash, class Eq, class... Ts>
295 
296 template <class Policy, class Hash, class Eq, class... Ts>
298  absl::void_t<decltype(Policy::apply(
299  RequireUsableKey<typename Policy::key_type, Hash, Eq>(),
300  std::declval<Ts>()...))>,
301  Policy, Hash, Eq, Ts...> : std::true_type {};
302 
303 // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
304 template <class T>
305 constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
306  using std::swap;
307  return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
308 }
309 template <class T>
310 constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
311  return false;
312 }
313 
314 template <typename T>
316  ABSL_ASSUME(x != 0);
317  return static_cast<uint32_t>(countr_zero(x));
318 }
319 
320 // An abstract bitmask, such as that emitted by a SIMD instruction.
321 //
322 // Specifically, this type implements a simple bitset whose representation is
323 // controlled by `SignificantBits` and `Shift`. `SignificantBits` is the number
324 // of abstract bits in the bitset, while `Shift` is the log-base-two of the
325 // width of an abstract bit in the representation.
326 // This mask provides operations for any number of real bits set in an abstract
327 // bit. To add iteration on top of that, implementation must guarantee no more
328 // than one real bit is set in an abstract bit.
329 template <class T, int SignificantBits, int Shift = 0>
331  public:
332  explicit NonIterableBitMask(T mask) : mask_(mask) {}
333 
334  explicit operator bool() const { return this->mask_ != 0; }
335 
336  // Returns the index of the lowest *abstract* bit set in `self`.
338  return container_internal::TrailingZeros(mask_) >> Shift;
339  }
340 
341  // Returns the index of the highest *abstract* bit set in `self`.
343  return static_cast<uint32_t>((bit_width(mask_) - 1) >> Shift);
344  }
345 
346  // Return the number of trailing zero *abstract* bits.
348  return container_internal::TrailingZeros(mask_) >> Shift;
349  }
350 
351  // Return the number of leading zero *abstract* bits.
353  constexpr int total_significant_bits = SignificantBits << Shift;
354  constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;
355  return static_cast<uint32_t>(countl_zero(mask_ << extra_bits)) >> Shift;
356  }
357 
359 };
360 
361 // Mask that can be iterable
362 //
363 // For example, when `SignificantBits` is 16 and `Shift` is zero, this is just
364 // an ordinary 16-bit bitset occupying the low 16 bits of `mask`. When
365 // `SignificantBits` is 8 and `Shift` is 3, abstract bits are represented as
366 // the bytes `0x00` and `0x80`, and it occupies all 64 bits of the bitmask.
367 //
368 // For example:
369 // for (int i : BitMask<uint32_t, 16>(0b101)) -> yields 0, 2
370 // for (int i : BitMask<uint64_t, 8, 3>(0x0000000080800000)) -> yields 2, 3
371 template <class T, int SignificantBits, int Shift = 0>
372 class BitMask : public NonIterableBitMask<T, SignificantBits, Shift> {
374  static_assert(std::is_unsigned<T>::value, "");
375  static_assert(Shift == 0 || Shift == 3, "");
376 
377  public:
378  explicit BitMask(T mask) : Base(mask) {}
379  // BitMask is an iterator over the indices of its abstract bits.
380  using value_type = int;
381  using iterator = BitMask;
383 
385  this->mask_ &= (this->mask_ - 1);
386  return *this;
387  }
388 
389  uint32_t operator*() const { return Base::LowestBitSet(); }
390 
391  BitMask begin() const { return *this; }
392  BitMask end() const { return BitMask(0); }
393 
394  private:
395  friend bool operator==(const BitMask& a, const BitMask& b) {
396  return a.mask_ == b.mask_;
397  }
398  friend bool operator!=(const BitMask& a, const BitMask& b) {
399  return a.mask_ != b.mask_;
400  }
401 };
402 
403 using h2_t = uint8_t;
404 
405 // The values here are selected for maximum performance. See the static asserts
406 // below for details.
407 
408 // A `ctrl_t` is a single control byte, which can have one of four
409 // states: empty, deleted, full (which has an associated seven-bit h2_t value)
410 // and the sentinel. They have the following bit patterns:
411 //
412 // empty: 1 0 0 0 0 0 0 0
413 // deleted: 1 1 1 1 1 1 1 0
414 // full: 0 h h h h h h h // h represents the hash bits.
415 // sentinel: 1 1 1 1 1 1 1 1
416 //
417 // These values are specifically tuned for SSE-flavored SIMD.
418 // The static_asserts below detail the source of these choices.
419 //
420 // We use an enum class so that when strict aliasing is enabled, the compiler
421 // knows ctrl_t doesn't alias other types.
422 enum class ctrl_t : int8_t {
423  kEmpty = -128, // 0b10000000
424  kDeleted = -2, // 0b11111110
425  kSentinel = -1, // 0b11111111
426 };
427 static_assert(
428  (static_cast<int8_t>(ctrl_t::kEmpty) &
429  static_cast<int8_t>(ctrl_t::kDeleted) &
430  static_cast<int8_t>(ctrl_t::kSentinel) & 0x80) != 0,
431  "Special markers need to have the MSB to make checking for them efficient");
432 static_assert(
434  "ctrl_t::kEmpty and ctrl_t::kDeleted must be smaller than "
435  "ctrl_t::kSentinel to make the SIMD test of IsEmptyOrDeleted() efficient");
436 static_assert(
437  ctrl_t::kSentinel == static_cast<ctrl_t>(-1),
438  "ctrl_t::kSentinel must be -1 to elide loading it from memory into SIMD "
439  "registers (pcmpeqd xmm, xmm)");
440 static_assert(ctrl_t::kEmpty == static_cast<ctrl_t>(-128),
441  "ctrl_t::kEmpty must be -128 to make the SIMD check for its "
442  "existence efficient (psignb xmm, xmm)");
443 static_assert(
444  (~static_cast<int8_t>(ctrl_t::kEmpty) &
445  ~static_cast<int8_t>(ctrl_t::kDeleted) &
446  static_cast<int8_t>(ctrl_t::kSentinel) & 0x7F) != 0,
447  "ctrl_t::kEmpty and ctrl_t::kDeleted must share an unset bit that is not "
448  "shared by ctrl_t::kSentinel to make the scalar test for "
449  "MaskEmptyOrDeleted() efficient");
450 static_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2),
451  "ctrl_t::kDeleted must be -2 to make the implementation of "
452  "ConvertSpecialToEmptyAndFullToDeleted efficient");
453 
454 ABSL_DLL extern const ctrl_t kEmptyGroup[16];
455 
456 // Returns a pointer to a control byte group that can be used by empty tables.
457 inline ctrl_t* EmptyGroup() {
458  // Const must be cast away here; no uses of this function will actually write
459  // to it, because it is only used for empty tables.
460  return const_cast<ctrl_t*>(kEmptyGroup);
461 }
462 
463 // Mixes a randomly generated per-process seed with `hash` and `ctrl` to
464 // randomize insertion order within groups.
465 bool ShouldInsertBackwards(size_t hash, const ctrl_t* ctrl);
466 
467 // Returns a per-table, hash salt, which changes on resize. This gets mixed into
468 // H1 to randomize iteration order per-table.
469 //
470 // The seed consists of the ctrl_ pointer, which adds enough entropy to ensure
471 // non-determinism of iteration order in most cases.
472 inline size_t PerTableSalt(const ctrl_t* ctrl) {
473  // The low bits of the pointer have little or no entropy because of
474  // alignment. We shift the pointer to try to use higher entropy bits. A
475  // good number seems to be 12 bits, because that aligns with page size.
476  return reinterpret_cast<uintptr_t>(ctrl) >> 12;
477 }
478 // Extracts the H1 portion of a hash: 57 bits mixed with a per-table salt.
479 inline size_t H1(size_t hash, const ctrl_t* ctrl) {
480  return (hash >> 7) ^ PerTableSalt(ctrl);
481 }
482 
483 // Extracts the H2 portion of a hash: the 7 bits not used for H1.
484 //
485 // These are used as an occupied control byte.
486 inline h2_t H2(size_t hash) { return hash & 0x7F; }
487 
488 // Helpers for checking the state of a control byte.
489 inline bool IsEmpty(ctrl_t c) { return c == ctrl_t::kEmpty; }
490 inline bool IsFull(ctrl_t c) { return c >= static_cast<ctrl_t>(0); }
491 inline bool IsDeleted(ctrl_t c) { return c == ctrl_t::kDeleted; }
492 inline bool IsEmptyOrDeleted(ctrl_t c) { return c < ctrl_t::kSentinel; }
493 
494 #ifdef ABSL_INTERNAL_HAVE_SSE2
495 // Quick reference guide for intrinsics used below:
496 //
497 // * __m128i: An XMM (128-bit) word.
498 //
499 // * _mm_setzero_si128: Returns a zero vector.
500 // * _mm_set1_epi8: Returns a vector with the same i8 in each lane.
501 //
502 // * _mm_subs_epi8: Saturating-subtracts two i8 vectors.
503 // * _mm_and_si128: Ands two i128s together.
504 // * _mm_or_si128: Ors two i128s together.
505 // * _mm_andnot_si128: And-nots two i128s together.
506 //
507 // * _mm_cmpeq_epi8: Component-wise compares two i8 vectors for equality,
508 // filling each lane with 0x00 or 0xff.
509 // * _mm_cmpgt_epi8: Same as above, but using > rather than ==.
510 //
511 // * _mm_loadu_si128: Performs an unaligned load of an i128.
512 // * _mm_storeu_si128: Performs an unaligned store of an i128.
513 //
514 // * _mm_sign_epi8: Retains, negates, or zeroes each i8 lane of the first
515 // argument if the corresponding lane of the second
516 // argument is positive, negative, or zero, respectively.
517 // * _mm_movemask_epi8: Selects the sign bit out of each i8 lane and produces a
518 // bitmask consisting of those bits.
519 // * _mm_shuffle_epi8: Selects i8s from the first argument, using the low
520 // four bits of each i8 lane in the second argument as
521 // indices.
522 
523 // https://github.com/abseil/abseil-cpp/issues/209
524 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
525 // _mm_cmpgt_epi8 is broken under GCC with -funsigned-char
526 // Work around this by using the portable implementation of Group
527 // when using -funsigned-char under GCC.
528 inline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) {
529 #if defined(__GNUC__) && !defined(__clang__)
531  const __m128i mask = _mm_set1_epi8(0x80);
532  const __m128i diff = _mm_subs_epi8(b, a);
533  return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask);
534  }
535 #endif
536  return _mm_cmpgt_epi8(a, b);
537 }
538 
539 struct GroupSse2Impl {
540  static constexpr size_t kWidth = 16; // the number of slots per group
541 
542  explicit GroupSse2Impl(const ctrl_t* pos) {
543  ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos));
544  }
545 
546  // Returns a bitmask representing the positions of slots that match hash.
547  BitMask<uint32_t, kWidth> Match(h2_t hash) const {
548  auto match = _mm_set1_epi8(hash);
549  return BitMask<uint32_t, kWidth>(
550  static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
551  }
552 
553  // Returns a bitmask representing the positions of empty slots.
554  NonIterableBitMask<uint32_t, kWidth> MaskEmpty() const {
555 #ifdef ABSL_INTERNAL_HAVE_SSSE3
556  // This only works because ctrl_t::kEmpty is -128.
557  return NonIterableBitMask<uint32_t, kWidth>(
558  static_cast<uint32_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl))));
559 #else
560  auto match = _mm_set1_epi8(static_cast<h2_t>(ctrl_t::kEmpty));
561  return NonIterableBitMask<uint32_t, kWidth>(
562  static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
563 #endif
564  }
565 
566  // Returns a bitmask representing the positions of empty or deleted slots.
567  NonIterableBitMask<uint32_t, kWidth> MaskEmptyOrDeleted() const {
568  auto special = _mm_set1_epi8(static_cast<uint8_t>(ctrl_t::kSentinel));
569  return NonIterableBitMask<uint32_t, kWidth>(static_cast<uint32_t>(
570  _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl))));
571  }
572 
573  // Returns the number of trailing empty or deleted elements in the group.
574  uint32_t CountLeadingEmptyOrDeleted() const {
575  auto special = _mm_set1_epi8(static_cast<uint8_t>(ctrl_t::kSentinel));
576  return TrailingZeros(static_cast<uint32_t>(
577  _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
578  }
579 
580  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
581  auto msbs = _mm_set1_epi8(static_cast<char>(-128));
582  auto x126 = _mm_set1_epi8(126);
583 #ifdef ABSL_INTERNAL_HAVE_SSSE3
584  auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
585 #else
586  auto zero = _mm_setzero_si128();
587  auto special_mask = _mm_cmpgt_epi8_fixed(zero, ctrl);
588  auto res = _mm_or_si128(msbs, _mm_andnot_si128(special_mask, x126));
589 #endif
590  _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res);
591  }
592 
593  __m128i ctrl;
594 };
595 #endif // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
596 
597 #if defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
598 struct GroupAArch64Impl {
599  static constexpr size_t kWidth = 8;
600 
601  explicit GroupAArch64Impl(const ctrl_t* pos) {
602  ctrl = vld1_u8(reinterpret_cast<const uint8_t*>(pos));
603  }
604 
605  BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const {
606  uint8x8_t dup = vdup_n_u8(hash);
607  auto mask = vceq_u8(ctrl, dup);
608  constexpr uint64_t msbs = 0x8080808080808080ULL;
609  return BitMask<uint64_t, kWidth, 3>(
610  vget_lane_u64(vreinterpret_u64_u8(mask), 0) & msbs);
611  }
612 
613  NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
614  uint64_t mask =
615  vget_lane_u64(vreinterpret_u64_u8(
616  vceq_s8(vdup_n_s8(static_cast<h2_t>(ctrl_t::kEmpty)),
617  vreinterpret_s8_u8(ctrl))),
618  0);
619  return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
620  }
621 
622  NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const {
623  uint64_t mask =
624  vget_lane_u64(vreinterpret_u64_u8(vcgt_s8(
625  vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
626  vreinterpret_s8_u8(ctrl))),
627  0);
628  return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
629  }
630 
631  uint32_t CountLeadingEmptyOrDeleted() const {
632  uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0);
633  // ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and
634  // kDeleted. We lower all other bits and count number of trailing zeros.
635  // Clang and GCC optimize countr_zero to rbit+clz without any check for 0,
636  // so we should be fine.
637  constexpr uint64_t bits = 0x0101010101010101ULL;
638  return countr_zero((mask | ~(mask >> 7)) & bits) >> 3;
639  }
640 
641  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
642  uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0);
643  constexpr uint64_t msbs = 0x8080808080808080ULL;
644  constexpr uint64_t lsbs = 0x0101010101010101ULL;
645  auto x = mask & msbs;
646  auto res = (~x + (x >> 7)) & ~lsbs;
648  }
649 
650  uint8x8_t ctrl;
651 };
652 #endif // ABSL_INTERNAL_HAVE_ARM_NEON && ABSL_IS_LITTLE_ENDIAN
653 
655  static constexpr size_t kWidth = 8;
656 
657  explicit GroupPortableImpl(const ctrl_t* pos)
658  : ctrl(little_endian::Load64(pos)) {}
659 
661  // For the technique, see:
662  // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
663  // (Determine if a word has a byte equal to n).
664  //
665  // Caveat: there are false positives but:
666  // - they only occur if there is a real match
667  // - they never occur on ctrl_t::kEmpty, ctrl_t::kDeleted, ctrl_t::kSentinel
668  // - they will be handled gracefully by subsequent checks in code
669  //
670  // Example:
671  // v = 0x1716151413121110
672  // hash = 0x12
673  // retval = (v - lsbs) & ~v & msbs = 0x0000000080800000
674  constexpr uint64_t msbs = 0x8080808080808080ULL;
675  constexpr uint64_t lsbs = 0x0101010101010101ULL;
676  auto x = ctrl ^ (lsbs * hash);
677  return BitMask<uint64_t, kWidth, 3>((x - lsbs) & ~x & msbs);
678  }
679 
681  constexpr uint64_t msbs = 0x8080808080808080ULL;
683  msbs);
684  }
685 
687  constexpr uint64_t msbs = 0x8080808080808080ULL;
689  msbs);
690  }
691 
693  // ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and
694  // kDeleted. We lower all other bits and count number of trailing zeros.
695  constexpr uint64_t bits = 0x0101010101010101ULL;
696  return countr_zero((ctrl | ~(ctrl >> 7)) & bits) >> 3;
697  }
698 
700  constexpr uint64_t msbs = 0x8080808080808080ULL;
701  constexpr uint64_t lsbs = 0x0101010101010101ULL;
702  auto x = ctrl & msbs;
703  auto res = (~x + (x >> 7)) & ~lsbs;
705  }
706 
708 };
709 
710 #ifdef ABSL_INTERNAL_HAVE_SSE2
711 using Group = GroupSse2Impl;
712 #elif defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
713 using Group = GroupAArch64Impl;
714 #else
716 #endif
717 
718 // Returns he number of "cloned control bytes".
719 //
720 // This is the number of control bytes that are present both at the beginning
721 // of the control byte array and at the end, such that we can create a
722 // `Group::kWidth`-width probe window starting from any control byte.
723 constexpr size_t NumClonedBytes() { return Group::kWidth - 1; }
724 
725 template <class Policy, class Hash, class Eq, class Alloc>
727 
728 // Returns whether `n` is a valid capacity (i.e., number of slots).
729 //
730 // A valid capacity is a non-zero integer `2^m - 1`.
731 inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
732 
733 // Applies the following mapping to every byte in the control array:
734 // * kDeleted -> kEmpty
735 // * kEmpty -> kEmpty
736 // * _ -> kDeleted
737 // PRECONDITION:
738 // IsValidCapacity(capacity)
739 // ctrl[capacity] == ctrl_t::kSentinel
740 // ctrl[i] != ctrl_t::kSentinel for all i < capacity
742 
743 // Converts `n` into the next valid capacity, per `IsValidCapacity`.
744 inline size_t NormalizeCapacity(size_t n) {
745  return n ? ~size_t{} >> countl_zero(n) : 1;
746 }
747 
748 // General notes on capacity/growth methods below:
749 // - We use 7/8th as maximum load factor. For 16-wide groups, that gives an
750 // average of two empty slots per group.
751 // - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity.
752 // - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we
753 // never need to probe (the whole table fits in one group) so we don't need a
754 // load factor less than 1.
755 
756 // Given `capacity`, applies the load factor; i.e., it returns the maximum
757 // number of values we should put into the table before a resizing rehash.
758 inline size_t CapacityToGrowth(size_t capacity) {
759  assert(IsValidCapacity(capacity));
760  // `capacity*7/8`
761  if (Group::kWidth == 8 && capacity == 7) {
762  // x-x/8 does not work when x==7.
763  return 6;
764  }
765  return capacity - capacity / 8;
766 }
767 
768 // Given `growth`, "unapplies" the load factor to find how large the capacity
769 // should be to stay within the load factor.
770 //
771 // This might not be a valid capacity and `NormalizeCapacity()` should be
772 // called on this.
773 inline size_t GrowthToLowerboundCapacity(size_t growth) {
774  // `growth*8/7`
775  if (Group::kWidth == 8 && growth == 7) {
776  // x+(x-1)/7 does not work when x==7.
777  return 8;
778  }
779  return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
780 }
781 
782 template <class InputIter>
783 size_t SelectBucketCountForIterRange(InputIter first, InputIter last,
784  size_t bucket_count) {
785  if (bucket_count != 0) {
786  return bucket_count;
787  }
788  using InputIterCategory =
789  typename std::iterator_traits<InputIter>::iterator_category;
790  if (std::is_base_of<std::random_access_iterator_tag,
791  InputIterCategory>::value) {
793  static_cast<size_t>(std::distance(first, last)));
794  }
795  return 0;
796 }
797 
798 #define ABSL_INTERNAL_ASSERT_IS_FULL(ctrl, msg) \
799  ABSL_HARDENING_ASSERT((ctrl != nullptr && IsFull(*ctrl)) && msg)
800 
801 inline void AssertIsValid(ctrl_t* ctrl) {
803  (ctrl == nullptr || IsFull(*ctrl)) &&
804  "Invalid operation on iterator. The element might have "
805  "been erased, the table might have rehashed, or this may "
806  "be an end() iterator.");
807 }
808 
809 struct FindInfo {
810  size_t offset;
811  size_t probe_length;
812 };
813 
814 // Whether a table is "small". A small table fits entirely into a probing
815 // group, i.e., has a capacity < `Group::kWidth`.
816 //
817 // In small mode we are able to use the whole capacity. The extra control
818 // bytes give us at least one "empty" control byte to stop the iteration.
819 // This is important to make 1 a valid capacity.
820 //
821 // In small mode only the first `capacity` control bytes after the sentinel
822 // are valid. The rest contain dummy ctrl_t::kEmpty values that do not
823 // represent a real slot. This is important to take into account on
824 // `find_first_non_full()`, where we never try
825 // `ShouldInsertBackwards()` for small tables.
826 inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; }
827 
828 // Begins a probing operation on `ctrl`, using `hash`.
829 inline probe_seq<Group::kWidth> probe(const ctrl_t* ctrl, size_t hash,
830  size_t capacity) {
831  return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity);
832 }
833 
834 // Probes an array of control bits using a probe sequence derived from `hash`,
835 // and returns the offset corresponding to the first deleted or empty slot.
836 //
837 // Behavior when the entire table is full is undefined.
838 //
839 // NOTE: this function must work with tables having both empty and deleted
840 // slots in the same group. Such tables appear during `erase()`.
841 template <typename = void>
842 inline FindInfo find_first_non_full(const ctrl_t* ctrl, size_t hash,
843  size_t capacity) {
844  auto seq = probe(ctrl, hash, capacity);
845  while (true) {
846  Group g{ctrl + seq.offset()};
847  auto mask = g.MaskEmptyOrDeleted();
848  if (mask) {
849 #if !defined(NDEBUG)
850  // We want to add entropy even when ASLR is not enabled.
851  // In debug build we will randomly insert in either the front or back of
852  // the group.
853  // TODO(kfm,sbenza): revisit after we do unconditional mixing
854  if (!is_small(capacity) && ShouldInsertBackwards(hash, ctrl)) {
855  return {seq.offset(mask.HighestBitSet()), seq.index()};
856  }
857 #endif
858  return {seq.offset(mask.LowestBitSet()), seq.index()};
859  }
860  seq.next();
861  assert(seq.index() <= capacity && "full table!");
862  }
863 }
864 
865 // Extern template for inline function keep possibility of inlining.
866 // When compiler decided to not inline, no symbols will be added to the
867 // corresponding translation unit.
868 extern template FindInfo find_first_non_full(const ctrl_t*, size_t, size_t);
869 
870 // Sets `ctrl` to `{kEmpty, kSentinel, ..., kEmpty}`, marking the entire
871 // array as marked as empty.
872 inline void ResetCtrl(size_t capacity, ctrl_t* ctrl, const void* slot,
873  size_t slot_size) {
874  std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
875  capacity + 1 + NumClonedBytes());
876  ctrl[capacity] = ctrl_t::kSentinel;
877  SanitizerPoisonMemoryRegion(slot, slot_size * capacity);
878 }
879 
880 // Sets `ctrl[i]` to `h`.
881 //
882 // Unlike setting it directly, this function will perform bounds checks and
883 // mirror the value to the cloned tail if necessary.
884 inline void SetCtrl(size_t i, ctrl_t h, size_t capacity, ctrl_t* ctrl,
885  const void* slot, size_t slot_size) {
886  assert(i < capacity);
887 
888  auto* slot_i = static_cast<const char*>(slot) + i * slot_size;
889  if (IsFull(h)) {
890  SanitizerUnpoisonMemoryRegion(slot_i, slot_size);
891  } else {
892  SanitizerPoisonMemoryRegion(slot_i, slot_size);
893  }
894 
895  ctrl[i] = h;
896  ctrl[((i - NumClonedBytes()) & capacity) + (NumClonedBytes() & capacity)] = h;
897 }
898 
899 // Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
900 inline void SetCtrl(size_t i, h2_t h, size_t capacity, ctrl_t* ctrl,
901  const void* slot, size_t slot_size) {
902  SetCtrl(i, static_cast<ctrl_t>(h), capacity, ctrl, slot, slot_size);
903 }
904 
905 // Given the capacity of a table, computes the offset (from the start of the
906 // backing allocation) at which the slots begin.
907 inline size_t SlotOffset(size_t capacity, size_t slot_align) {
908  assert(IsValidCapacity(capacity));
909  const size_t num_control_bytes = capacity + 1 + NumClonedBytes();
910  return (num_control_bytes + slot_align - 1) & (~slot_align + 1);
911 }
912 
913 // Given the capacity of a table, computes the total size of the backing
914 // array.
915 inline size_t AllocSize(size_t capacity, size_t slot_size, size_t slot_align) {
916  return SlotOffset(capacity, slot_align) + capacity * slot_size;
917 }
918 
919 // A SwissTable.
920 //
921 // Policy: a policy defines how to perform different operations on
922 // the slots of the hashtable (see hash_policy_traits.h for the full interface
923 // of policy).
924 //
925 // Hash: a (possibly polymorphic) functor that hashes keys of the hashtable. The
926 // functor should accept a key and return size_t as hash. For best performance
927 // it is important that the hash function provides high entropy across all bits
928 // of the hash.
929 //
930 // Eq: a (possibly polymorphic) functor that compares two keys for equality. It
931 // should accept two (of possibly different type) keys and return a bool: true
932 // if they are equal, false if they are not. If two keys compare equal, then
933 // their hash values as defined by Hash MUST be equal.
934 //
935 // Allocator: an Allocator
936 // [https://en.cppreference.com/w/cpp/named_req/Allocator] with which
937 // the storage of the hashtable will be allocated and the elements will be
938 // constructed and destroyed.
939 template <class Policy, class Hash, class Eq, class Alloc>
940 class raw_hash_set {
942  using KeyArgImpl =
944 
945  public:
948  // TODO(sbenza): Hide slot_type as it is an implementation detail. Needs user
949  // code fixes!
952  using size_type = size_t;
953  using difference_type = ptrdiff_t;
954  using hasher = Hash;
955  using key_equal = Eq;
956  using policy_type = Policy;
959  using const_reference = const value_type&;
960  using pointer = typename absl::allocator_traits<
961  allocator_type>::template rebind_traits<value_type>::pointer;
962  using const_pointer = typename absl::allocator_traits<
964 
965  // Alias used for heterogeneous lookup functions.
966  // `key_arg<K>` evaluates to `K` when the functors are transparent and to
967  // `key_type` otherwise. It permits template argument deduction on `K` for the
968  // transparent case.
969  template <class K>
970  using key_arg = typename KeyArgImpl::template type<K, key_type>;
971 
972  private:
973  // Give an early error when key_type is not hashable/eq.
974  auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k));
975  auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k));
976 
978  using SlotAlloc = typename absl::allocator_traits<
979  allocator_type>::template rebind_alloc<slot_type>;
980  using SlotAllocTraits = typename absl::allocator_traits<
981  allocator_type>::template rebind_traits<slot_type>;
982 
984  "Policy::element() must return a reference");
985 
986  template <typename T>
988  : std::is_same<typename std::remove_cv<
989  typename std::remove_reference<reference>::type>::type,
990  typename std::remove_cv<
991  typename std::remove_reference<T>::type>::type> {};
992 
993  // An enabler for insert(T&&): T must be convertible to init_type or be the
994  // same as [cv] value_type [ref].
995  // Note: we separate SameAsElementReference into its own type to avoid using
996  // reference unless we need to. MSVC doesn't seem to like it in some
997  // cases.
998  template <class T>
999  using RequiresInsertable = typename std::enable_if<
1002  int>::type;
1003 
1004  // RequiresNotInit is a workaround for gcc prior to 7.1.
1005  // See https://godbolt.org/g/Y4xsUh.
1006  template <class T>
1007  using RequiresNotInit =
1009 
1010  template <class... Ts>
1012 
1013  public:
1015  "Allocators with custom pointer types are not supported");
1017  "Allocators with custom pointer types are not supported");
1018 
1019  class iterator {
1020  friend class raw_hash_set;
1021 
1022  public:
1023  using iterator_category = std::forward_iterator_tag;
1025  using reference =
1030 
1032 
1033  // PRECONDITION: not an end() iterator.
1036  "operator*() called on invalid iterator.");
1037  return PolicyTraits::element(slot_);
1038  }
1039 
1040  // PRECONDITION: not an end() iterator.
1043  "operator-> called on invalid iterator.");
1044  return &operator*();
1045  }
1046 
1047  // PRECONDITION: not an end() iterator.
1050  "operator++ called on invalid iterator.");
1051  ++ctrl_;
1052  ++slot_;
1053  skip_empty_or_deleted();
1054  return *this;
1055  }
1056  // PRECONDITION: not an end() iterator.
1058  auto tmp = *this;
1059  ++*this;
1060  return tmp;
1061  }
1062 
1063  friend bool operator==(const iterator& a, const iterator& b) {
1064  AssertIsValid(a.ctrl_);
1065  AssertIsValid(b.ctrl_);
1066  return a.ctrl_ == b.ctrl_;
1067  }
1068  friend bool operator!=(const iterator& a, const iterator& b) {
1069  return !(a == b);
1070  }
1071 
1072  private:
1073  iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {
1074  // This assumption helps the compiler know that any non-end iterator is
1075  // not equal to any end iterator.
1076  ABSL_ASSUME(ctrl != nullptr);
1077  }
1078 
1079  // Fixes up `ctrl_` to point to a full by advancing it and `slot_` until
1080  // they reach one.
1081  //
1082  // If a sentinel is reached, we null both of them out instead.
1084  while (IsEmptyOrDeleted(*ctrl_)) {
1085  uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted();
1086  ctrl_ += shift;
1087  slot_ += shift;
1088  }
1089  if (ABSL_PREDICT_FALSE(*ctrl_ == ctrl_t::kSentinel)) ctrl_ = nullptr;
1090  }
1091 
1092  ctrl_t* ctrl_ = nullptr;
1093  // To avoid uninitialized member warnings, put slot_ in an anonymous union.
1094  // The member is not initialized on singleton and end iterators.
1095  union {
1097  };
1098  };
1099 
1101  friend class raw_hash_set;
1102 
1103  public:
1109 
1111  // Implicit construction from iterator.
1112  const_iterator(iterator i) : inner_(std::move(i)) {}
1113 
1114  reference operator*() const { return *inner_; }
1115  pointer operator->() const { return inner_.operator->(); }
1116 
1118  ++inner_;
1119  return *this;
1120  }
1121  const_iterator operator++(int) { return inner_++; }
1122 
1123  friend bool operator==(const const_iterator& a, const const_iterator& b) {
1124  return a.inner_ == b.inner_;
1125  }
1126  friend bool operator!=(const const_iterator& a, const const_iterator& b) {
1127  return !(a == b);
1128  }
1129 
1130  private:
1131  const_iterator(const ctrl_t* ctrl, const slot_type* slot)
1132  : inner_(const_cast<ctrl_t*>(ctrl), const_cast<slot_type*>(slot)) {}
1133 
1135  };
1136 
1139 
1140  raw_hash_set() noexcept(
1141  std::is_nothrow_default_constructible<hasher>::value&&
1142  std::is_nothrow_default_constructible<key_equal>::value&&
1143  std::is_nothrow_default_constructible<allocator_type>::value) {}
1144 
1145  explicit raw_hash_set(size_t bucket_count, const hasher& hash = hasher(),
1146  const key_equal& eq = key_equal(),
1147  const allocator_type& alloc = allocator_type())
1148  : ctrl_(EmptyGroup()),
1149  settings_(0, HashtablezInfoHandle(), hash, eq, alloc) {
1150  if (bucket_count) {
1151  capacity_ = NormalizeCapacity(bucket_count);
1152  initialize_slots();
1153  }
1154  }
1155 
1156  raw_hash_set(size_t bucket_count, const hasher& hash,
1157  const allocator_type& alloc)
1158  : raw_hash_set(bucket_count, hash, key_equal(), alloc) {}
1159 
1160  raw_hash_set(size_t bucket_count, const allocator_type& alloc)
1161  : raw_hash_set(bucket_count, hasher(), key_equal(), alloc) {}
1162 
1164  : raw_hash_set(0, hasher(), key_equal(), alloc) {}
1165 
1166  template <class InputIter>
1167  raw_hash_set(InputIter first, InputIter last, size_t bucket_count = 0,
1168  const hasher& hash = hasher(), const key_equal& eq = key_equal(),
1169  const allocator_type& alloc = allocator_type())
1170  : raw_hash_set(SelectBucketCountForIterRange(first, last, bucket_count),
1171  hash, eq, alloc) {
1172  insert(first, last);
1173  }
1174 
1175  template <class InputIter>
1176  raw_hash_set(InputIter first, InputIter last, size_t bucket_count,
1177  const hasher& hash, const allocator_type& alloc)
1178  : raw_hash_set(first, last, bucket_count, hash, key_equal(), alloc) {}
1179 
1180  template <class InputIter>
1181  raw_hash_set(InputIter first, InputIter last, size_t bucket_count,
1182  const allocator_type& alloc)
1183  : raw_hash_set(first, last, bucket_count, hasher(), key_equal(), alloc) {}
1184 
1185  template <class InputIter>
1186  raw_hash_set(InputIter first, InputIter last, const allocator_type& alloc)
1187  : raw_hash_set(first, last, 0, hasher(), key_equal(), alloc) {}
1188 
1189  // Instead of accepting std::initializer_list<value_type> as the first
1190  // argument like std::unordered_set<value_type> does, we have two overloads
1191  // that accept std::initializer_list<T> and std::initializer_list<init_type>.
1192  // This is advantageous for performance.
1193  //
1194  // // Turns {"abc", "def"} into std::initializer_list<std::string>, then
1195  // // copies the strings into the set.
1196  // std::unordered_set<std::string> s = {"abc", "def"};
1197  //
1198  // // Turns {"abc", "def"} into std::initializer_list<const char*>, then
1199  // // copies the strings into the set.
1200  // absl::flat_hash_set<std::string> s = {"abc", "def"};
1201  //
1202  // The same trick is used in insert().
1203  //
1204  // The enabler is necessary to prevent this constructor from triggering where
1205  // the copy constructor is meant to be called.
1206  //
1207  // absl::flat_hash_set<int> a, b{a};
1208  //
1209  // RequiresNotInit<T> is a workaround for gcc prior to 7.1.
1210  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
1211  raw_hash_set(std::initializer_list<T> init, size_t bucket_count = 0,
1212  const hasher& hash = hasher(), const key_equal& eq = key_equal(),
1213  const allocator_type& alloc = allocator_type())
1214  : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}
1215 
1216  raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count = 0,
1217  const hasher& hash = hasher(), const key_equal& eq = key_equal(),
1218  const allocator_type& alloc = allocator_type())
1219  : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}
1220 
1221  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
1222  raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
1223  const hasher& hash, const allocator_type& alloc)
1224  : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
1225 
1226  raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,
1227  const hasher& hash, const allocator_type& alloc)
1228  : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
1229 
1230  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
1231  raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
1232  const allocator_type& alloc)
1233  : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
1234 
1235  raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,
1236  const allocator_type& alloc)
1237  : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
1238 
1239  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
1240  raw_hash_set(std::initializer_list<T> init, const allocator_type& alloc)
1241  : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}
1242 
1243  raw_hash_set(std::initializer_list<init_type> init,
1244  const allocator_type& alloc)
1245  : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}
1246 
1248  : raw_hash_set(that, AllocTraits::select_on_container_copy_construction(
1249  that.alloc_ref())) {}
1250 
1252  : raw_hash_set(0, that.hash_ref(), that.eq_ref(), a) {
1253  reserve(that.size());
1254  // Because the table is guaranteed to be empty, we can do something faster
1255  // than a full `insert`.
1256  for (const auto& v : that) {
1257  const size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, v);
1258  auto target = find_first_non_full(ctrl_, hash, capacity_);
1259  SetCtrl(target.offset, H2(hash), capacity_, ctrl_, slots_,
1260  sizeof(slot_type));
1261  emplace_at(target.offset, v);
1262  infoz().RecordInsert(hash, target.probe_length);
1263  }
1264  size_ = that.size();
1265  growth_left() -= that.size();
1266  }
1267 
1268  raw_hash_set(raw_hash_set&& that) noexcept(
1272  : ctrl_(absl::exchange(that.ctrl_, EmptyGroup())),
1273  slots_(absl::exchange(that.slots_, nullptr)),
1274  size_(absl::exchange(that.size_, 0)),
1275  capacity_(absl::exchange(that.capacity_, 0)),
1276  // Hash, equality and allocator are copied instead of moved because
1277  // `that` must be left valid. If Hash is std::function<Key>, moving it
1278  // would create a nullptr functor that cannot be called.
1279  settings_(absl::exchange(that.growth_left(), 0),
1280  absl::exchange(that.infoz(), HashtablezInfoHandle()),
1281  that.hash_ref(), that.eq_ref(), that.alloc_ref()) {}
1282 
1284  : ctrl_(EmptyGroup()),
1285  slots_(nullptr),
1286  size_(0),
1287  capacity_(0),
1288  settings_(0, HashtablezInfoHandle(), that.hash_ref(), that.eq_ref(),
1289  a) {
1290  if (a == that.alloc_ref()) {
1291  std::swap(ctrl_, that.ctrl_);
1292  std::swap(slots_, that.slots_);
1293  std::swap(size_, that.size_);
1294  std::swap(capacity_, that.capacity_);
1295  std::swap(growth_left(), that.growth_left());
1296  std::swap(infoz(), that.infoz());
1297  } else {
1298  reserve(that.size());
1299  // Note: this will copy elements of dense_set and unordered_set instead of
1300  // moving them. This can be fixed if it ever becomes an issue.
1301  for (auto& elem : that) insert(std::move(elem));
1302  }
1303  }
1304 
1306  raw_hash_set tmp(that,
1308  ? that.alloc_ref()
1309  : alloc_ref());
1310  swap(tmp);
1311  return *this;
1312  }
1313 
1318  // TODO(sbenza): We should only use the operations from the noexcept clause
1319  // to make sure we actually adhere to that contract.
1320  return move_assign(
1321  std::move(that),
1323  }
1324 
1325  ~raw_hash_set() { destroy_slots(); }
1326 
1328  auto it = iterator_at(0);
1329  it.skip_empty_or_deleted();
1330  return it;
1331  }
1332  iterator end() { return {}; }
1333 
1334  const_iterator begin() const {
1335  return const_cast<raw_hash_set*>(this)->begin();
1336  }
1337  const_iterator end() const { return {}; }
1338  const_iterator cbegin() const { return begin(); }
1339  const_iterator cend() const { return end(); }
1340 
1341  bool empty() const { return !size(); }
1342  size_t size() const { return size_; }
1343  size_t capacity() const { return capacity_; }
1344  size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
1345 
1347  // Iterating over this container is O(bucket_count()). When bucket_count()
1348  // is much greater than size(), iteration becomes prohibitively expensive.
1349  // For clear() it is more important to reuse the allocated array when the
1350  // container is small because allocation takes comparatively long time
1351  // compared to destruction of the elements of the container. So we pick the
1352  // largest bucket_count() threshold for which iteration is still fast and
1353  // past that we simply deallocate the array.
1354  if (capacity_ > 127) {
1355  destroy_slots();
1356 
1357  infoz().RecordClearedReservation();
1358  } else if (capacity_) {
1359  for (size_t i = 0; i != capacity_; ++i) {
1360  if (IsFull(ctrl_[i])) {
1361  PolicyTraits::destroy(&alloc_ref(), slots_ + i);
1362  }
1363  }
1364  size_ = 0;
1365  ResetCtrl(capacity_, ctrl_, slots_, sizeof(slot_type));
1366  reset_growth_left();
1367  }
1368  assert(empty());
1369  infoz().RecordStorageChanged(0, capacity_);
1370  }
1371 
1372  // This overload kicks in when the argument is an rvalue of insertable and
1373  // decomposable type other than init_type.
1374  //
1375  // flat_hash_map<std::string, int> m;
1376  // m.insert(std::make_pair("abc", 42));
1377  // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
1378  // bug.
1379  template <class T, RequiresInsertable<T> = 0, class T2 = T,
1380  typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
1381  T* = nullptr>
1382  std::pair<iterator, bool> insert(T&& value) {
1383  return emplace(std::forward<T>(value));
1384  }
1385 
1386  // This overload kicks in when the argument is a bitfield or an lvalue of
1387  // insertable and decomposable type.
1388  //
1389  // union { int n : 1; };
1390  // flat_hash_set<int> s;
1391  // s.insert(n);
1392  //
1393  // flat_hash_set<std::string> s;
1394  // const char* p = "hello";
1395  // s.insert(p);
1396  //
1397  // TODO(romanp): Once we stop supporting gcc 5.1 and below, replace
1398  // RequiresInsertable<T> with RequiresInsertable<const T&>.
1399  // We are hitting this bug: https://godbolt.org/g/1Vht4f.
1400  template <
1401  class T, RequiresInsertable<T> = 0,
1403  std::pair<iterator, bool> insert(const T& value) {
1404  return emplace(value);
1405  }
1406 
1407  // This overload kicks in when the argument is an rvalue of init_type. Its
1408  // purpose is to handle brace-init-list arguments.
1409  //
1410  // flat_hash_map<std::string, int> s;
1411  // s.insert({"abc", 42});
1412  std::pair<iterator, bool> insert(init_type&& value) {
1413  return emplace(std::move(value));
1414  }
1415 
1416  // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
1417  // bug.
1418  template <class T, RequiresInsertable<T> = 0, class T2 = T,
1419  typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
1420  T* = nullptr>
1421  iterator insert(const_iterator, T&& value) {
1422  return insert(std::forward<T>(value)).first;
1423  }
1424 
1425  // TODO(romanp): Once we stop supporting gcc 5.1 and below, replace
1426  // RequiresInsertable<T> with RequiresInsertable<const T&>.
1427  // We are hitting this bug: https://godbolt.org/g/1Vht4f.
1428  template <
1429  class T, RequiresInsertable<T> = 0,
1431  iterator insert(const_iterator, const T& value) {
1432  return insert(value).first;
1433  }
1434 
1435  iterator insert(const_iterator, init_type&& value) {
1436  return insert(std::move(value)).first;
1437  }
1438 
1439  template <class InputIt>
1440  void insert(InputIt first, InputIt last) {
1441  for (; first != last; ++first) emplace(*first);
1442  }
1443 
1444  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0>
1445  void insert(std::initializer_list<T> ilist) {
1446  insert(ilist.begin(), ilist.end());
1447  }
1448 
1449  void insert(std::initializer_list<init_type> ilist) {
1450  insert(ilist.begin(), ilist.end());
1451  }
1452 
1454  if (!node) return {end(), false, node_type()};
1455  const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node));
1456  auto res = PolicyTraits::apply(
1457  InsertSlot<false>{*this, std::move(*CommonAccess::GetSlot(node))},
1458  elem);
1459  if (res.second) {
1460  CommonAccess::Reset(&node);
1461  return {res.first, true, node_type()};
1462  } else {
1463  return {res.first, false, std::move(node)};
1464  }
1465  }
1466 
1467  iterator insert(const_iterator, node_type&& node) {
1468  auto res = insert(std::move(node));
1469  node = std::move(res.node);
1470  return res.position;
1471  }
1472 
1473  // This overload kicks in if we can deduce the key from args. This enables us
1474  // to avoid constructing value_type if an entry with the same key already
1475  // exists.
1476  //
1477  // For example:
1478  //
1479  // flat_hash_map<std::string, std::string> m = {{"abc", "def"}};
1480  // // Creates no std::string copies and makes no heap allocations.
1481  // m.emplace("abc", "xyz");
1482  template <class... Args, typename std::enable_if<
1483  IsDecomposable<Args...>::value, int>::type = 0>
1484  std::pair<iterator, bool> emplace(Args&&... args) {
1485  return PolicyTraits::apply(EmplaceDecomposable{*this},
1486  std::forward<Args>(args)...);
1487  }
1488 
1489  // This overload kicks in if we cannot deduce the key from args. It constructs
1490  // value_type unconditionally and then either moves it into the table or
1491  // destroys.
1492  template <class... Args, typename std::enable_if<
1493  !IsDecomposable<Args...>::value, int>::type = 0>
1494  std::pair<iterator, bool> emplace(Args&&... args) {
1495  alignas(slot_type) unsigned char raw[sizeof(slot_type)];
1496  slot_type* slot = reinterpret_cast<slot_type*>(&raw);
1497 
1498  PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
1499  const auto& elem = PolicyTraits::element(slot);
1500  return PolicyTraits::apply(InsertSlot<true>{*this, std::move(*slot)}, elem);
1501  }
1502 
1503  template <class... Args>
1504  iterator emplace_hint(const_iterator, Args&&... args) {
1505  return emplace(std::forward<Args>(args)...).first;
1506  }
1507 
1508  // Extension API: support for lazy emplace.
1509  //
1510  // Looks up key in the table. If found, returns the iterator to the element.
1511  // Otherwise calls `f` with one argument of type `raw_hash_set::constructor`.
1512  //
1513  // `f` must abide by several restrictions:
1514  // - it MUST call `raw_hash_set::constructor` with arguments as if a
1515  // `raw_hash_set::value_type` is constructed,
1516  // - it MUST NOT access the container before the call to
1517  // `raw_hash_set::constructor`, and
1518  // - it MUST NOT erase the lazily emplaced element.
1519  // Doing any of these is undefined behavior.
1520  //
1521  // For example:
1522  //
1523  // std::unordered_set<ArenaString> s;
1524  // // Makes ArenaStr even if "abc" is in the map.
1525  // s.insert(ArenaString(&arena, "abc"));
1526  //
1527  // flat_hash_set<ArenaStr> s;
1528  // // Makes ArenaStr only if "abc" is not in the map.
1529  // s.lazy_emplace("abc", [&](const constructor& ctor) {
1530  // ctor(&arena, "abc");
1531  // });
1532  //
1533  // WARNING: This API is currently experimental. If there is a way to implement
1534  // the same thing with the rest of the API, prefer that.
1535  class constructor {
1536  friend class raw_hash_set;
1537 
1538  public:
1539  template <class... Args>
1540  void operator()(Args&&... args) const {
1541  assert(*slot_);
1542  PolicyTraits::construct(alloc_, *slot_, std::forward<Args>(args)...);
1543  *slot_ = nullptr;
1544  }
1545 
1546  private:
1547  constructor(allocator_type* a, slot_type** slot) : alloc_(a), slot_(slot) {}
1548 
1551  };
1552 
1553  template <class K = key_type, class F>
1555  auto res = find_or_prepare_insert(key);
1556  if (res.second) {
1557  slot_type* slot = slots_ + res.first;
1558  std::forward<F>(f)(constructor(&alloc_ref(), &slot));
1559  assert(!slot);
1560  }
1561  return iterator_at(res.first);
1562  }
1563 
1564  // Extension API: support for heterogeneous keys.
1565  //
1566  // std::unordered_set<std::string> s;
1567  // // Turns "abc" into std::string.
1568  // s.erase("abc");
1569  //
1570  // flat_hash_set<std::string> s;
1571  // // Uses "abc" directly without copying it into std::string.
1572  // s.erase("abc");
1573  template <class K = key_type>
1575  auto it = find(key);
1576  if (it == end()) return 0;
1577  erase(it);
1578  return 1;
1579  }
1580 
1581  // Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`,
1582  // this method returns void to reduce algorithmic complexity to O(1). The
1583  // iterator is invalidated, so any increment should be done before calling
1584  // erase. In order to erase while iterating across a map, use the following
1585  // idiom (which also works for standard containers):
1586  //
1587  // for (auto it = m.begin(), end = m.end(); it != end;) {
1588  // // `erase()` will invalidate `it`, so advance `it` first.
1589  // auto copy_it = it++;
1590  // if (<pred>) {
1591  // m.erase(copy_it);
1592  // }
1593  // }
1594  void erase(const_iterator cit) { erase(cit.inner_); }
1595 
1596  // This overload is necessary because otherwise erase<K>(const K&) would be
1597  // a better match if non-const iterator is passed as an argument.
1600  "erase() called on invalid iterator.");
1601  PolicyTraits::destroy(&alloc_ref(), it.slot_);
1602  erase_meta_only(it);
1603  }
1604 
1605  iterator erase(const_iterator first, const_iterator last) {
1606  while (first != last) {
1607  erase(first++);
1608  }
1609  return last.inner_;
1610  }
1611 
1612  // Moves elements from `src` into `this`.
1613  // If the element already exists in `this`, it is left unmodified in `src`.
1614  template <typename H, typename E>
1616  assert(this != &src);
1617  for (auto it = src.begin(), e = src.end(); it != e;) {
1618  auto next = std::next(it);
1619  if (PolicyTraits::apply(InsertSlot<false>{*this, std::move(*it.slot_)},
1620  PolicyTraits::element(it.slot_))
1621  .second) {
1622  src.erase_meta_only(it);
1623  }
1624  it = next;
1625  }
1626  }
1627 
1628  template <typename H, typename E>
1630  merge(src);
1631  }
1632 
1633  node_type extract(const_iterator position) {
1635  "extract() called on invalid iterator.");
1636  auto node =
1637  CommonAccess::Transfer<node_type>(alloc_ref(), position.inner_.slot_);
1638  erase_meta_only(position);
1639  return node;
1640  }
1641 
1642  template <
1643  class K = key_type,
1646  auto it = find(key);
1647  return it == end() ? node_type() : extract(const_iterator{it});
1648  }
1649 
1650  void swap(raw_hash_set& that) noexcept(
1651  IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
1652  IsNoThrowSwappable<allocator_type>(
1654  using std::swap;
1655  swap(ctrl_, that.ctrl_);
1656  swap(slots_, that.slots_);
1657  swap(size_, that.size_);
1658  swap(capacity_, that.capacity_);
1659  swap(growth_left(), that.growth_left());
1660  swap(hash_ref(), that.hash_ref());
1661  swap(eq_ref(), that.eq_ref());
1662  swap(infoz(), that.infoz());
1663  SwapAlloc(alloc_ref(), that.alloc_ref(),
1664  typename AllocTraits::propagate_on_container_swap{});
1665  }
1666 
1667  void rehash(size_t n) {
1668  if (n == 0 && capacity_ == 0) return;
1669  if (n == 0 && size_ == 0) {
1670  destroy_slots();
1671  infoz().RecordStorageChanged(0, 0);
1672  infoz().RecordClearedReservation();
1673  return;
1674  }
1675 
1676  // bitor is a faster way of doing `max` here. We will round up to the next
1677  // power-of-2-minus-1, so bitor is good enough.
1679  // n == 0 unconditionally rehashes as per the standard.
1680  if (n == 0 || m > capacity_) {
1681  resize(m);
1682 
1683  // This is after resize, to ensure that we have completed the allocation
1684  // and have potentially sampled the hashtable.
1685  infoz().RecordReservation(n);
1686  }
1687  }
1688 
1689  void reserve(size_t n) {
1690  if (n > size() + growth_left()) {
1691  size_t m = GrowthToLowerboundCapacity(n);
1692  resize(NormalizeCapacity(m));
1693 
1694  // This is after resize, to ensure that we have completed the allocation
1695  // and have potentially sampled the hashtable.
1696  infoz().RecordReservation(n);
1697  }
1698  }
1699 
1700  // Extension API: support for heterogeneous keys.
1701  //
1702  // std::unordered_set<std::string> s;
1703  // // Turns "abc" into std::string.
1704  // s.count("abc");
1705  //
1706  // ch_set<std::string> s;
1707  // // Uses "abc" directly without copying it into std::string.
1708  // s.count("abc");
1709  template <class K = key_type>
1710  size_t count(const key_arg<K>& key) const {
1711  return find(key) == end() ? 0 : 1;
1712  }
1713 
1714  // Issues CPU prefetch instructions for the memory needed to find or insert
1715  // a key. Like all lookup functions, this support heterogeneous keys.
1716  //
1717  // NOTE: This is a very low level operation and should not be used without
1718  // specific benchmarks indicating its importance.
1719  template <class K = key_type>
1720  void prefetch(const key_arg<K>& key) const {
1721  (void)key;
1722  // Avoid probing if we won't be able to prefetch the addresses received.
1723 #ifdef ABSL_INTERNAL_HAVE_PREFETCH
1724  prefetch_heap_block();
1725  auto seq = probe(ctrl_, hash_ref()(key), capacity_);
1726  base_internal::PrefetchT0(ctrl_ + seq.offset());
1727  base_internal::PrefetchT0(slots_ + seq.offset());
1728 #endif // ABSL_INTERNAL_HAVE_PREFETCH
1729  }
1730 
1731  // The API of find() has two extensions.
1732  //
1733  // 1. The hash can be passed by the user. It must be equal to the hash of the
1734  // key.
1735  //
1736  // 2. The type of the key argument doesn't have to be key_type. This is so
1737  // called heterogeneous key support.
1738  template <class K = key_type>
1739  iterator find(const key_arg<K>& key, size_t hash) {
1740  auto seq = probe(ctrl_, hash, capacity_);
1741  while (true) {
1742  Group g{ctrl_ + seq.offset()};
1743  for (uint32_t i : g.Match(H2(hash))) {
1745  EqualElement<K>{key, eq_ref()},
1746  PolicyTraits::element(slots_ + seq.offset(i)))))
1747  return iterator_at(seq.offset(i));
1748  }
1749  if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return end();
1750  seq.next();
1751  assert(seq.index() <= capacity_ && "full table!");
1752  }
1753  }
1754  template <class K = key_type>
1756  prefetch_heap_block();
1757  return find(key, hash_ref()(key));
1758  }
1759 
1760  template <class K = key_type>
1761  const_iterator find(const key_arg<K>& key, size_t hash) const {
1762  return const_cast<raw_hash_set*>(this)->find(key, hash);
1763  }
1764  template <class K = key_type>
1765  const_iterator find(const key_arg<K>& key) const {
1766  prefetch_heap_block();
1767  return find(key, hash_ref()(key));
1768  }
1769 
1770  template <class K = key_type>
1771  bool contains(const key_arg<K>& key) const {
1772  return find(key) != end();
1773  }
1774 
1775  template <class K = key_type>
1776  std::pair<iterator, iterator> equal_range(const key_arg<K>& key) {
1777  auto it = find(key);
1778  if (it != end()) return {it, std::next(it)};
1779  return {it, it};
1780  }
1781  template <class K = key_type>
1782  std::pair<const_iterator, const_iterator> equal_range(
1783  const key_arg<K>& key) const {
1784  auto it = find(key);
1785  if (it != end()) return {it, std::next(it)};
1786  return {it, it};
1787  }
1788 
1789  size_t bucket_count() const { return capacity_; }
1790  float load_factor() const {
1791  return capacity_ ? static_cast<double>(size()) / capacity_ : 0.0;
1792  }
1793  float max_load_factor() const { return 1.0f; }
1794  void max_load_factor(float) {
1795  // Does nothing.
1796  }
1797 
1798  hasher hash_function() const { return hash_ref(); }
1799  key_equal key_eq() const { return eq_ref(); }
1800  allocator_type get_allocator() const { return alloc_ref(); }
1801 
1802  friend bool operator==(const raw_hash_set& a, const raw_hash_set& b) {
1803  if (a.size() != b.size()) return false;
1804  const raw_hash_set* outer = &a;
1805  const raw_hash_set* inner = &b;
1806  if (outer->capacity() > inner->capacity()) std::swap(outer, inner);
1807  for (const value_type& elem : *outer)
1808  if (!inner->has_element(elem)) return false;
1809  return true;
1810  }
1811 
1812  friend bool operator!=(const raw_hash_set& a, const raw_hash_set& b) {
1813  return !(a == b);
1814  }
1815 
1816  template <typename H>
1818  H>::type
1820  return H::combine(H::combine_unordered(std::move(h), s.begin(), s.end()),
1821  s.size());
1822  }
1823 
1824  friend void swap(raw_hash_set& a,
1825  raw_hash_set& b) noexcept(noexcept(a.swap(b))) {
1826  a.swap(b);
1827  }
1828 
1829  private:
1830  template <class Container, typename Enabler>
1832  HashtableDebugAccess;
1833 
1835  template <class K, class... Args>
1836  const_iterator operator()(const K& key, Args&&...) const {
1837  return s.find(key);
1838  }
1839  const raw_hash_set& s;
1840  };
1841 
1842  struct HashElement {
1843  template <class K, class... Args>
1844  size_t operator()(const K& key, Args&&...) const {
1845  return h(key);
1846  }
1847  const hasher& h;
1848  };
1849 
1850  template <class K1>
1851  struct EqualElement {
1852  template <class K2, class... Args>
1853  bool operator()(const K2& lhs, Args&&...) const {
1854  return eq(lhs, rhs);
1855  }
1856  const K1& rhs;
1857  const key_equal& eq;
1858  };
1859 
1861  template <class K, class... Args>
1862  std::pair<iterator, bool> operator()(const K& key, Args&&... args) const {
1863  auto res = s.find_or_prepare_insert(key);
1864  if (res.second) {
1865  s.emplace_at(res.first, std::forward<Args>(args)...);
1866  }
1867  return {s.iterator_at(res.first), res.second};
1868  }
1870  };
1871 
1872  template <bool do_destroy>
1873  struct InsertSlot {
1874  template <class K, class... Args>
1875  std::pair<iterator, bool> operator()(const K& key, Args&&...) && {
1876  auto res = s.find_or_prepare_insert(key);
1877  if (res.second) {
1878  PolicyTraits::transfer(&s.alloc_ref(), s.slots_ + res.first, &slot);
1879  } else if (do_destroy) {
1880  PolicyTraits::destroy(&s.alloc_ref(), &slot);
1881  }
1882  return {s.iterator_at(res.first), res.second};
1883  }
1885  // Constructed slot. Either moved into place or destroyed.
1887  };
1888 
1889  // Erases, but does not destroy, the value pointed to by `it`.
1890  //
1891  // This merely updates the pertinent control byte. This can be used in
1892  // conjunction with Policy::transfer to move the object to another place.
1893  void erase_meta_only(const_iterator it) {
1894  assert(IsFull(*it.inner_.ctrl_) && "erasing a dangling iterator");
1895  --size_;
1896  const size_t index = static_cast<size_t>(it.inner_.ctrl_ - ctrl_);
1897  const size_t index_before = (index - Group::kWidth) & capacity_;
1898  const auto empty_after = Group(it.inner_.ctrl_).MaskEmpty();
1899  const auto empty_before = Group(ctrl_ + index_before).MaskEmpty();
1900 
1901  // We count how many consecutive non empties we have to the right and to the
1902  // left of `it`. If the sum is >= kWidth then there is at least one probe
1903  // window that might have seen a full group.
1904  bool was_never_full =
1905  empty_before && empty_after &&
1906  static_cast<size_t>(empty_after.TrailingZeros() +
1907  empty_before.LeadingZeros()) < Group::kWidth;
1908 
1909  SetCtrl(index, was_never_full ? ctrl_t::kEmpty : ctrl_t::kDeleted,
1910  capacity_, ctrl_, slots_, sizeof(slot_type));
1911  growth_left() += was_never_full;
1912  infoz().RecordErase();
1913  }
1914 
1915  // Allocates a backing array for `self` and initializes its control bytes.
1916  // This reads `capacity_` and updates all other fields based on the result of
1917  // the allocation.
1918  //
1919  // This does not free the currently held array; `capacity_` must be nonzero.
1921  assert(capacity_);
1922  // Folks with custom allocators often make unwarranted assumptions about the
1923  // behavior of their classes vis-a-vis trivial destructability and what
1924  // calls they will or wont make. Avoid sampling for people with custom
1925  // allocators to get us out of this mess. This is not a hard guarantee but
1926  // a workaround while we plan the exact guarantee we want to provide.
1927  //
1928  // People are often sloppy with the exact type of their allocator (sometimes
1929  // it has an extra const or is missing the pair, but rebinds made it work
1930  // anyway). To avoid the ambiguity, we work off SlotAlloc which we have
1931  // bound more carefully.
1932  if (std::is_same<SlotAlloc, std::allocator<slot_type>>::value &&
1933  slots_ == nullptr) {
1934  infoz() = Sample(sizeof(slot_type));
1935  }
1936 
1937  char* mem = static_cast<char*>(Allocate<alignof(slot_type)>(
1938  &alloc_ref(),
1939  AllocSize(capacity_, sizeof(slot_type), alignof(slot_type))));
1940  ctrl_ = reinterpret_cast<ctrl_t*>(mem);
1941  slots_ = reinterpret_cast<slot_type*>(
1942  mem + SlotOffset(capacity_, alignof(slot_type)));
1943  ResetCtrl(capacity_, ctrl_, slots_, sizeof(slot_type));
1944  reset_growth_left();
1945  infoz().RecordStorageChanged(size_, capacity_);
1946  }
1947 
1948  // Destroys all slots in the backing array, frees the backing array, and
1949  // clears all top-level book-keeping data.
1950  //
1951  // This essentially implements `map = raw_hash_set();`.
1952  void destroy_slots() {
1953  if (!capacity_) return;
1954  for (size_t i = 0; i != capacity_; ++i) {
1955  if (IsFull(ctrl_[i])) {
1956  PolicyTraits::destroy(&alloc_ref(), slots_ + i);
1957  }
1958  }
1959 
1960  // Unpoison before returning the memory to the allocator.
1962  Deallocate<alignof(slot_type)>(
1963  &alloc_ref(), ctrl_,
1964  AllocSize(capacity_, sizeof(slot_type), alignof(slot_type)));
1965  ctrl_ = EmptyGroup();
1966  slots_ = nullptr;
1967  size_ = 0;
1968  capacity_ = 0;
1969  growth_left() = 0;
1970  }
1971 
1972  void resize(size_t new_capacity) {
1973  assert(IsValidCapacity(new_capacity));
1974  auto* old_ctrl = ctrl_;
1975  auto* old_slots = slots_;
1976  const size_t old_capacity = capacity_;
1977  capacity_ = new_capacity;
1978  initialize_slots();
1979 
1980  size_t total_probe_length = 0;
1981  for (size_t i = 0; i != old_capacity; ++i) {
1982  if (IsFull(old_ctrl[i])) {
1983  size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
1984  PolicyTraits::element(old_slots + i));
1985  auto target = find_first_non_full(ctrl_, hash, capacity_);
1986  size_t new_i = target.offset;
1987  total_probe_length += target.probe_length;
1988  SetCtrl(new_i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
1989  PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, old_slots + i);
1990  }
1991  }
1992  if (old_capacity) {
1994  sizeof(slot_type) * old_capacity);
1995  Deallocate<alignof(slot_type)>(
1996  &alloc_ref(), old_ctrl,
1997  AllocSize(old_capacity, sizeof(slot_type), alignof(slot_type)));
1998  }
1999  infoz().RecordRehash(total_probe_length);
2000  }
2001 
2002  // Prunes control bytes to remove as many tombstones as possible.
2003  //
2004  // See the comment on `rehash_and_grow_if_necessary()`.
2006  assert(IsValidCapacity(capacity_));
2007  assert(!is_small(capacity_));
2008  // Algorithm:
2009  // - mark all DELETED slots as EMPTY
2010  // - mark all FULL slots as DELETED
2011  // - for each slot marked as DELETED
2012  // hash = Hash(element)
2013  // target = find_first_non_full(hash)
2014  // if target is in the same group
2015  // mark slot as FULL
2016  // else if target is EMPTY
2017  // transfer element to target
2018  // mark slot as EMPTY
2019  // mark target as FULL
2020  // else if target is DELETED
2021  // swap current element with target element
2022  // mark target as FULL
2023  // repeat procedure for current slot with moved from element (target)
2025  alignas(slot_type) unsigned char raw[sizeof(slot_type)];
2026  size_t total_probe_length = 0;
2027  slot_type* slot = reinterpret_cast<slot_type*>(&raw);
2028  for (size_t i = 0; i != capacity_; ++i) {
2029  if (!IsDeleted(ctrl_[i])) continue;
2030  const size_t hash = PolicyTraits::apply(
2031  HashElement{hash_ref()}, PolicyTraits::element(slots_ + i));
2033  const size_t new_i = target.offset;
2034  total_probe_length += target.probe_length;
2035 
2036  // Verify if the old and new i fall within the same group wrt the hash.
2037  // If they do, we don't need to move the object as it falls already in the
2038  // best probe we can.
2039  const size_t probe_offset = probe(ctrl_, hash, capacity_).offset();
2040  const auto probe_index = [probe_offset, this](size_t pos) {
2041  return ((pos - probe_offset) & capacity_) / Group::kWidth;
2042  };
2043 
2044  // Element doesn't move.
2045  if (ABSL_PREDICT_TRUE(probe_index(new_i) == probe_index(i))) {
2046  SetCtrl(i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
2047  continue;
2048  }
2049  if (IsEmpty(ctrl_[new_i])) {
2050  // Transfer element to the empty spot.
2051  // SetCtrl poisons/unpoisons the slots so we have to call it at the
2052  // right time.
2053  SetCtrl(new_i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
2054  PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, slots_ + i);
2055  SetCtrl(i, ctrl_t::kEmpty, capacity_, ctrl_, slots_, sizeof(slot_type));
2056  } else {
2057  assert(IsDeleted(ctrl_[new_i]));
2058  SetCtrl(new_i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
2059  // Until we are done rehashing, DELETED marks previously FULL slots.
2060  // Swap i and new_i elements.
2061  PolicyTraits::transfer(&alloc_ref(), slot, slots_ + i);
2062  PolicyTraits::transfer(&alloc_ref(), slots_ + i, slots_ + new_i);
2063  PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, slot);
2064  --i; // repeat
2065  }
2066  }
2067  reset_growth_left();
2068  infoz().RecordRehash(total_probe_length);
2069  }
2070 
2071  // Called whenever the table *might* need to conditionally grow.
2072  //
2073  // This function is an optimization opportunity to perform a rehash even when
2074  // growth is unnecessary, because vacating tombstones is beneficial for
2075  // performance in the long-run.
2077  if (capacity_ == 0) {
2078  resize(1);
2079  } else if (capacity_ > Group::kWidth &&
2080  // Do these calcuations in 64-bit to avoid overflow.
2081  size() * uint64_t{32} <= capacity_ * uint64_t{25}) {
2082  // Squash DELETED without growing if there is enough capacity.
2083  //
2084  // Rehash in place if the current size is <= 25/32 of capacity_.
2085  // Rationale for such a high factor: 1) drop_deletes_without_resize() is
2086  // faster than resize, and 2) it takes quite a bit of work to add
2087  // tombstones. In the worst case, seems to take approximately 4
2088  // insert/erase pairs to create a single tombstone and so if we are
2089  // rehashing because of tombstones, we can afford to rehash-in-place as
2090  // long as we are reclaiming at least 1/8 the capacity without doing more
2091  // than 2X the work. (Where "work" is defined to be size() for rehashing
2092  // or rehashing in place, and 1 for an insert or erase.) But rehashing in
2093  // place is faster per operation than inserting or even doubling the size
2094  // of the table, so we actually afford to reclaim even less space from a
2095  // resize-in-place. The decision is to rehash in place if we can reclaim
2096  // at about 1/8th of the usable capacity (specifically 3/28 of the
2097  // capacity) which means that the total cost of rehashing will be a small
2098  // fraction of the total work.
2099  //
2100  // Here is output of an experiment using the BM_CacheInSteadyState
2101  // benchmark running the old case (where we rehash-in-place only if we can
2102  // reclaim at least 7/16*capacity_) vs. this code (which rehashes in place
2103  // if we can recover 3/32*capacity_).
2104  //
2105  // Note that although in the worst-case number of rehashes jumped up from
2106  // 15 to 190, but the number of operations per second is almost the same.
2107  //
2108  // Abridged output of running BM_CacheInSteadyState benchmark from
2109  // raw_hash_set_benchmark. N is the number of insert/erase operations.
2110  //
2111  // | OLD (recover >= 7/16 | NEW (recover >= 3/32)
2112  // size | N/s LoadFactor NRehashes | N/s LoadFactor NRehashes
2113  // 448 | 145284 0.44 18 | 140118 0.44 19
2114  // 493 | 152546 0.24 11 | 151417 0.48 28
2115  // 538 | 151439 0.26 11 | 151152 0.53 38
2116  // 583 | 151765 0.28 11 | 150572 0.57 50
2117  // 628 | 150241 0.31 11 | 150853 0.61 66
2118  // 672 | 149602 0.33 12 | 150110 0.66 90
2119  // 717 | 149998 0.35 12 | 149531 0.70 129
2120  // 762 | 149836 0.37 13 | 148559 0.74 190
2121  // 807 | 149736 0.39 14 | 151107 0.39 14
2122  // 852 | 150204 0.42 15 | 151019 0.42 15
2123  drop_deletes_without_resize();
2124  } else {
2125  // Otherwise grow the container.
2126  resize(capacity_ * 2 + 1);
2127  }
2128  }
2129 
2130  bool has_element(const value_type& elem) const {
2131  size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, elem);
2132  auto seq = probe(ctrl_, hash, capacity_);
2133  while (true) {
2134  Group g{ctrl_ + seq.offset()};
2135  for (uint32_t i : g.Match(H2(hash))) {
2136  if (ABSL_PREDICT_TRUE(PolicyTraits::element(slots_ + seq.offset(i)) ==
2137  elem))
2138  return true;
2139  }
2140  if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return false;
2141  seq.next();
2142  assert(seq.index() <= capacity_ && "full table!");
2143  }
2144  return false;
2145  }
2146 
2147  // TODO(alkis): Optimize this assuming *this and that don't overlap.
2149  raw_hash_set tmp(std::move(that));
2150  swap(tmp);
2151  return *this;
2152  }
2154  raw_hash_set tmp(std::move(that), alloc_ref());
2155  swap(tmp);
2156  return *this;
2157  }
2158 
2159  protected:
2160  // Attempts to find `key` in the table; if it isn't found, returns a slot that
2161  // the value can be inserted into, with the control byte already set to
2162  // `key`'s H2.
2163  template <class K>
2164  std::pair<size_t, bool> find_or_prepare_insert(const K& key) {
2165  prefetch_heap_block();
2166  auto hash = hash_ref()(key);
2167  auto seq = probe(ctrl_, hash, capacity_);
2168  while (true) {
2169  Group g{ctrl_ + seq.offset()};
2170  for (uint32_t i : g.Match(H2(hash))) {
2172  EqualElement<K>{key, eq_ref()},
2173  PolicyTraits::element(slots_ + seq.offset(i)))))
2174  return {seq.offset(i), false};
2175  }
2176  if (ABSL_PREDICT_TRUE(g.MaskEmpty())) break;
2177  seq.next();
2178  assert(seq.index() <= capacity_ && "full table!");
2179  }
2180  return {prepare_insert(hash), true};
2181  }
2182 
2183  // Given the hash of a value not currently in the table, finds the next
2184  // viable slot index to insert it at.
2185  //
2186  // REQUIRES: At least one non-full slot available.
2188  auto target = find_first_non_full(ctrl_, hash, capacity_);
2189  if (ABSL_PREDICT_FALSE(growth_left() == 0 &&
2190  !IsDeleted(ctrl_[target.offset]))) {
2191  rehash_and_grow_if_necessary();
2193  }
2194  ++size_;
2195  growth_left() -= IsEmpty(ctrl_[target.offset]);
2196  SetCtrl(target.offset, H2(hash), capacity_, ctrl_, slots_,
2197  sizeof(slot_type));
2198  infoz().RecordInsert(hash, target.probe_length);
2199  return target.offset;
2200  }
2201 
2202  // Constructs the value in the space pointed by the iterator. This only works
2203  // after an unsuccessful find_or_prepare_insert() and before any other
2204  // modifications happen in the raw_hash_set.
2205  //
2206  // PRECONDITION: i is an index returned from find_or_prepare_insert(k), where
2207  // k is the key decomposed from `forward<Args>(args)...`, and the bool
2208  // returned by find_or_prepare_insert(k) was true.
2209  // POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...).
2210  template <class... Args>
2211  void emplace_at(size_t i, Args&&... args) {
2212  PolicyTraits::construct(&alloc_ref(), slots_ + i,
2213  std::forward<Args>(args)...);
2214 
2215  assert(PolicyTraits::apply(FindElement{*this}, *iterator_at(i)) ==
2216  iterator_at(i) &&
2217  "constructed value does not match the lookup key");
2218  }
2219 
2220  iterator iterator_at(size_t i) { return {ctrl_ + i, slots_ + i}; }
2221  const_iterator iterator_at(size_t i) const { return {ctrl_ + i, slots_ + i}; }
2222 
2223  private:
2225 
2227  growth_left() = CapacityToGrowth(capacity()) - size_;
2228  }
2229 
2230  // The number of slots we can still fill without needing to rehash.
2231  //
2232  // This is stored separately due to tombstones: we do not include tombstones
2233  // in the growth capacity, because we'd like to rehash when the table is
2234  // otherwise filled with tombstones: otherwise, probe sequences might get
2235  // unacceptably long without triggering a rehash. Callers can also force a
2236  // rehash via the standard `rehash(0)`, which will recompute this value as a
2237  // side-effect.
2238  //
2239  // See `CapacityToGrowth()`.
2240  size_t& growth_left() { return settings_.template get<0>(); }
2241 
2242  // Prefetch the heap-allocated memory region to resolve potential TLB misses.
2243  // This is intended to overlap with execution of calculating the hash for a
2244  // key.
2245  void prefetch_heap_block() const {
2247  }
2248 
2249  HashtablezInfoHandle& infoz() { return settings_.template get<1>(); }
2250 
2251  hasher& hash_ref() { return settings_.template get<2>(); }
2252  const hasher& hash_ref() const { return settings_.template get<2>(); }
2253  key_equal& eq_ref() { return settings_.template get<3>(); }
2254  const key_equal& eq_ref() const { return settings_.template get<3>(); }
2255  allocator_type& alloc_ref() { return settings_.template get<4>(); }
2256  const allocator_type& alloc_ref() const {
2257  return settings_.template get<4>();
2258  }
2259 
2260  // TODO(alkis): Investigate removing some of these fields:
2261  // - ctrl/slots can be derived from each other
2262  // - size can be moved into the slot array
2263 
2264  // The control bytes (and, also, a pointer to the base of the backing array).
2265  //
2266  // This contains `capacity_ + 1 + NumClonedBytes()` entries, even
2267  // when the table is empty (hence EmptyGroup).
2268  ctrl_t* ctrl_ = EmptyGroup();
2269  // The beginning of the slots, located at `SlotOffset()` bytes after
2270  // `ctrl_`. May be null for empty tables.
2271  slot_type* slots_ = nullptr;
2272 
2273  // The number of filled slots.
2274  size_t size_ = 0;
2275 
2276  // The total number of available slots.
2277  size_t capacity_ = 0;
2278  absl::container_internal::CompressedTuple<size_t /* growth_left */,
2282  allocator_type{}};
2283 };
2284 
2285 // Erases all elements that satisfy the predicate `pred` from the container `c`.
2286 template <typename P, typename H, typename E, typename A, typename Predicate>
2288  Predicate& pred, raw_hash_set<P, H, E, A>* c) {
2289  const auto initial_size = c->size();
2290  for (auto it = c->begin(), last = c->end(); it != last;) {
2291  if (pred(*it)) {
2292  c->erase(it++);
2293  } else {
2294  ++it;
2295  }
2296  }
2297  return initial_size - c->size();
2298 }
2299 
2300 namespace hashtable_debug_internal {
2301 template <typename Set>
2302 struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
2303  using Traits = typename Set::PolicyTraits;
2304  using Slot = typename Traits::slot_type;
2305 
2306  static size_t GetNumProbes(const Set& set,
2307  const typename Set::key_type& key) {
2308  size_t num_probes = 0;
2309  size_t hash = set.hash_ref()(key);
2310  auto seq = probe(set.ctrl_, hash, set.capacity_);
2311  while (true) {
2312  container_internal::Group g{set.ctrl_ + seq.offset()};
2313  for (uint32_t i : g.Match(container_internal::H2(hash))) {
2314  if (Traits::apply(
2315  typename Set::template EqualElement<typename Set::key_type>{
2316  key, set.eq_ref()},
2317  Traits::element(set.slots_ + seq.offset(i))))
2318  return num_probes;
2319  ++num_probes;
2320  }
2321  if (g.MaskEmpty()) return num_probes;
2322  seq.next();
2323  ++num_probes;
2324  }
2325  }
2326 
2327  static size_t AllocatedByteSize(const Set& c) {
2328  size_t capacity = c.capacity_;
2329  if (capacity == 0) return 0;
2330  size_t m = AllocSize(capacity, sizeof(Slot), alignof(Slot));
2331 
2332  size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
2333  if (per_slot != ~size_t{}) {
2334  m += per_slot * c.size();
2335  } else {
2336  for (size_t i = 0; i != capacity; ++i) {
2337  if (container_internal::IsFull(c.ctrl_[i])) {
2338  m += Traits::space_used(c.slots_ + i);
2339  }
2340  }
2341  }
2342  return m;
2343  }
2344 
2345  static size_t LowerBoundAllocatedByteSize(size_t size) {
2347  if (capacity == 0) return 0;
2348  size_t m =
2349  AllocSize(NormalizeCapacity(capacity), sizeof(Slot), alignof(Slot));
2350  size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
2351  if (per_slot != ~size_t{}) {
2352  m += per_slot * size;
2353  }
2354  return m;
2355  }
2356 };
2357 
2358 } // namespace hashtable_debug_internal
2359 } // namespace container_internal
2361 } // namespace absl
2362 
2363 #undef ABSL_INTERNAL_ASSERT_IS_FULL
2364 
2365 #endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
absl::container_internal::is_small
bool is_small(size_t capacity)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:826
ABSL_PREDICT_FALSE
#define ABSL_PREDICT_FALSE(x)
Definition: abseil-cpp/absl/base/optimization.h:180
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::init_type
typename PolicyTraits::init_type init_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:946
absl::container_internal::BitMask::begin
BitMask begin() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:391
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::IsDecomposable
IsDecomposable< void, PolicyTraits, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, Ts... > IsDecomposable
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1011
absl::container_internal::probe_seq::mask_
size_t mask_
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:278
absl::container_internal::raw_hash_set::extract
node_type extract(const_iterator position)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1633
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::const_pointer
typename absl::allocator_traits< allocator_type >::template rebind_traits< value_type >::const_pointer const_pointer
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:963
absl::container_internal::probe_seq::index_
size_t index_
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:280
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(const raw_hash_set &that, const allocator_type &a)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1251
absl::container_internal::probe
probe_seq< Group::kWidth > probe(const ctrl_t *ctrl, size_t hash, size_t capacity)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:829
absl::container_internal::hashtable_debug_internal::HashtableDebugAccess< Set, absl::void_t< typename Set::raw_hash_set > >::GetNumProbes
static size_t GetNumProbes(const Set &set, const typename Set::key_type &key)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2306
absl::container_internal::raw_hash_set::insert
std::pair< iterator, bool > insert(init_type &&value)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1412
absl::container_internal::raw_hash_set::find
const_iterator find(const key_arg< K > &key, size_t hash) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1761
absl::container_internal::hash_policy_traits
Definition: abseil-cpp/absl/container/internal/hash_policy_traits.h:32
dst
static const char dst[]
Definition: test-fs-copyfile.c:37
absl::FormatConversionChar::E
@ E
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(raw_hash_set &&that, const allocator_type &a)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1283
regen-readme.it
it
Definition: regen-readme.py:15
init
const char * init
Definition: upb/upb/bindings/lua/main.c:49
absl::container_internal::raw_hash_set::operator!=
friend bool operator!=(const raw_hash_set &a, const raw_hash_set &b)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1812
element
static std::function< Slot &(Slot *)> element
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:44
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(std::initializer_list< init_type > init, size_t bucket_count=0, const hasher &hash=hasher(), const key_equal &eq=key_equal(), const allocator_type &alloc=allocator_type())
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1216
absl::container_internal::raw_hash_set::insert
void insert(std::initializer_list< init_type > ilist)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1449
pos
int pos
Definition: libuv/docs/code/tty-gravity/main.c:11
absl::container_internal::raw_hash_set::iterator_at
iterator iterator_at(size_t i)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2220
bool
bool
Definition: setup_once.h:312
absl::container_internal::raw_hash_set::find
iterator find(const key_arg< K > &key)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1755
absl::container_internal::raw_hash_set::FindElement
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1834
absl::container_internal::hashtable_debug_internal::HashtableDebugAccess< Set, absl::void_t< typename Set::raw_hash_set > >::Traits
typename Set::PolicyTraits Traits
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2303
find
static void ** find(grpc_chttp2_stream_map *map, uint32_t key)
Definition: stream_map.cc:99
memset
return memset(p, 0, total)
absl::container_internal::raw_hash_set::end
const_iterator end() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1337
absl::container_internal::raw_hash_set::alloc_ref
allocator_type & alloc_ref()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2255
reserve
static bool reserve(upb_pb_encoder *e, size_t bytes)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:7630
absl::container_internal::raw_hash_set::insert
iterator insert(const_iterator, const T &value)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1431
absl::container_internal::raw_hash_set::const_iterator::operator->
pointer operator->() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1115
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(InputIter first, InputIter last, size_t bucket_count=0, const hasher &hash=hasher(), const key_equal &eq=key_equal(), const allocator_type &alloc=allocator_type())
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1167
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(std::initializer_list< T > init, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1240
absl::container_internal::raw_hash_set::iterator::iterator
iterator(ctrl_t *ctrl, slot_type *slot)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1073
begin
char * begin
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1007
absl::container_internal::raw_hash_set::constructor::constructor
constructor(allocator_type *a, slot_type **slot)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1547
absl::container_internal::raw_hash_set::const_iterator::value_type
typename raw_hash_set::value_type value_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1105
absl::little_endian::Store64
void Store64(void *p, uint64_t v)
Definition: abseil-cpp/absl/base/internal/endian.h:183
absl::container_internal::raw_hash_set::load_factor
float load_factor() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1790
absl::container_internal::raw_hash_set::insert
iterator insert(const_iterator, node_type &&node)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1467
capacity
uint16_t capacity
Definition: protobuf/src/google/protobuf/descriptor.cc:948
absl::container_internal::BitMask::BitMask
BitMask(T mask)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:378
absl::container_internal::raw_hash_set::merge
void merge(raw_hash_set< Policy, H, E, Alloc > &&src)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1629
absl::allocator_traits::propagate_on_container_swap
memory_internal::ExtractOrT< memory_internal::GetPropagateOnContainerSwap, Alloc, std::false_type > propagate_on_container_swap
Definition: third_party/abseil-cpp/absl/memory/memory.h:493
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::reference
value_type & reference
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:958
absl::container_internal::raw_hash_set::prefetch
void prefetch(const key_arg< K > &key) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1720
absl::container_internal::raw_hash_set::initialize_slots
void initialize_slots()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1920
absl::container_internal::raw_hash_set::clear
ABSL_ATTRIBUTE_REINITIALIZES void clear()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1346
position
intern position
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/array.c:487
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::const_reference
const value_type & const_reference
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:959
absl::container_internal::FindInfo::probe_length
size_t probe_length
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:811
absl::allocator_traits::propagate_on_container_move_assignment
memory_internal::ExtractOrT< memory_internal::GetPropagateOnContainerMoveAssignment, Alloc, std::false_type > propagate_on_container_move_assignment
Definition: third_party/abseil-cpp/absl/memory/memory.h:487
match
unsigned char match[65280+2]
Definition: bloaty/third_party/zlib/examples/gun.c:165
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(size_t bucket_count, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1160
absl::container_internal::raw_hash_set::get_allocator
allocator_type get_allocator() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1800
absl::container_internal::raw_hash_set::EqualElement::operator()
bool operator()(const K2 &lhs, Args &&...) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1853
google::protobuf.internal::true_type
integral_constant< bool, true > true_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:89
absl::container_internal::GroupPortableImpl
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:654
absl::container_internal::NonIterableBitMask::mask_
T mask_
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:358
absl::container_internal::raw_hash_set::operator==
friend bool operator==(const raw_hash_set &a, const raw_hash_set &b)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1802
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(std::initializer_list< T > init, size_t bucket_count=0, const hasher &hash=hasher(), const key_equal &eq=key_equal(), const allocator_type &alloc=allocator_type())
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1211
absl::container_internal::probe_seq::next
void next()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:269
absl::conditional_t
typename std::conditional< B, T, F >::type conditional_t
Definition: abseil-cpp/absl/meta/type_traits.h:634
google::protobuf.internal::false_type
integral_constant< bool, false > false_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:90
elem
Timer elem
Definition: event_engine/iomgr_event_engine/timer_heap_test.cc:109
absl::container_internal::raw_hash_set::insert
std::pair< iterator, bool > insert(T &&value)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1382
absl::container_internal::BitMask
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:372
absl::container_internal::H2
h2_t H2(size_t hash)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:486
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
absl::container_internal::raw_hash_set::eq_ref
key_equal & eq_ref()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2253
absl::container_internal::raw_hash_set::find
iterator find(const key_arg< K > &key, size_t hash)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1739
absl::container_internal::raw_hash_set::iterator::iterator
iterator()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1031
apply
MockFunction< int(int)> apply
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:94
absl::FormatConversionChar::s
@ s
absl::container_internal::HashtablezInfoHandle
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:228
a
int a
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:88
absl::container_internal::raw_hash_set::max_size
size_t max_size() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1344
absl::container_internal::raw_hash_set::find_or_prepare_insert
std::pair< size_t, bool > find_or_prepare_insert(const K &key)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2164
absl::container_internal::raw_hash_set::iterator::value_type
typename raw_hash_set::value_type value_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1024
absl::container_internal::kEmpty
@ kEmpty
absl::container_internal::raw_hash_set::EqualElement::eq
const key_equal & eq
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1857
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set() noexcept(std::is_nothrow_default_constructible< hasher >::value &&std::is_nothrow_default_constructible< key_equal >::value &&std::is_nothrow_default_constructible< allocator_type >::value)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1140
absl::container_internal::raw_hash_set::reset_growth_left
void reset_growth_left()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2226
absl::container_internal::raw_hash_set::has_element
bool has_element(const value_type &elem) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2130
absl::allocator_traits
Definition: third_party/abseil-cpp/absl/memory/memory.h:427
absl::container_internal::raw_hash_set::growth_left
size_t & growth_left()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2240
second
StrT second
Definition: cxa_demangle.cpp:4885
absl::container_internal::raw_hash_set::resize
void resize(size_t new_capacity)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1972
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::container_internal::hashtable_debug_internal::HashtableDebugAccess< Set, absl::void_t< typename Set::raw_hash_set > >::LowerBoundAllocatedByteSize
static size_t LowerBoundAllocatedByteSize(size_t size)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2345
absl::container_internal::raw_hash_set::iterator::operator->
pointer operator->() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1041
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
iterator
const typedef MCPhysReg * iterator
Definition: MCRegisterInfo.h:27
absl::container_internal::AllocSize
size_t AllocSize(size_t capacity, size_t slot_size, size_t slot_align)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:915
setup.k
k
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
absl::base_internal::PrefetchT2
void PrefetchT2(const void *addr)
Definition: prefetch.h:130
absl::container_internal::raw_hash_set::HashElement::h
const hasher & h
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1847
ABSL_HARDENING_ASSERT
#define ABSL_HARDENING_ASSERT(expr)
Definition: abseil-cpp/absl/base/macros.h:134
absl::container_internal::raw_hash_set::insert
std::pair< iterator, bool > insert(const T &value)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1403
absl::container_internal::raw_hash_set::EmplaceDecomposable::s
raw_hash_set & s
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1869
T
#define T(upbtypeconst, upbtype, ctype, default_value)
absl::container_internal::raw_hash_set::SameAsElementReference
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:987
absl::container_internal::raw_hash_set::iterator::operator*
reference operator*() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1034
gen_build_yaml.struct
def struct(**kwargs)
Definition: test/core/end2end/gen_build_yaml.py:30
absl::container_internal::raw_hash_set::const_iterator::operator++
const_iterator & operator++()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1117
absl::container_internal::FindInfo
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:809
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(const raw_hash_set &that)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1247
absl::container_internal::raw_hash_set::move_assign
raw_hash_set & move_assign(raw_hash_set &&that, std::false_type)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2153
absl::container_internal::probe_seq
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:254
absl::container_internal::raw_hash_set::equal_range
std::pair< const_iterator, const_iterator > equal_range(const key_arg< K > &key) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1782
absl::container_internal::raw_hash_set::iterator::operator==
friend bool operator==(const iterator &a, const iterator &b)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1063
ABSL_ATTRIBUTE_NOINLINE
#define ABSL_ATTRIBUTE_NOINLINE
Definition: abseil-cpp/absl/base/attributes.h:112
absl::container_internal::raw_hash_set::begin
iterator begin()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1327
absl::container_internal::raw_hash_set::erase
size_type erase(const key_arg< K > &key)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1574
absl::container_internal::raw_hash_set::const_iterator
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1100
absl::container_internal::GroupPortableImpl::ConvertSpecialToEmptyAndFullToDeleted
void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t *dst) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:699
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(size_t bucket_count, const hasher &hash, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1156
hash
uint64_t hash
Definition: ring_hash.cc:284
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(std::initializer_list< init_type > init, size_t bucket_count, const hasher &hash, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1226
absl::operator*
uint128 operator*(uint128 lhs, uint128 rhs)
Definition: abseil-cpp/absl/numeric/int128.h:977
absl::container_internal::CapacityToGrowth
size_t CapacityToGrowth(size_t capacity)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:758
absl::container_internal::probe_seq::probe_seq
probe_seq(size_t hash, size_t mask)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:259
absl::container_internal::raw_hash_set::AbslHashValue
friend std::enable_if< H::template is_hashable< value_type >::value, H >::type AbslHashValue(H h, const raw_hash_set &s)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1819
absl::container_internal::find_first_non_full
template FindInfo find_first_non_full(const ctrl_t *, size_t, size_t)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:842
absl::container_internal::raw_hash_set::iterator_at
const_iterator iterator_at(size_t i) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2221
ULL
#define ULL(x)
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/coded_stream_unittest.cc:57
absl::container_internal::raw_hash_set::erase_meta_only
void erase_meta_only(const_iterator it)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1893
absl::container_internal::raw_hash_set::operator=
raw_hash_set & operator=(const raw_hash_set &that)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1305
absl::container_internal::raw_hash_set::contains
bool contains(const key_arg< K > &key) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1771
hasher
hash_default_hash< T > hasher
Definition: abseil-cpp/absl/container/internal/hash_function_defaults_test.cc:88
absl::container_internal::CommonAccess::GetSlot
static auto GetSlot(const Node &node) -> decltype(node.slot())
Definition: abseil-cpp/absl/container/internal/common.h:170
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(size_t bucket_count, const hasher &hash=hasher(), const key_equal &eq=key_equal(), const allocator_type &alloc=allocator_type())
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1145
absl::FormatConversionChar::e
@ e
absl::container_internal::raw_hash_set::end
iterator end()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1332
absl::container_internal::raw_hash_set::iterator::difference_type
typename raw_hash_set::difference_type difference_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1029
absl::container_internal::probe_seq::offset
size_t offset(size_t i) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:267
c
void c(T a)
Definition: miscompile_with_no_unique_address_test.cc:40
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::container_internal::IsDeleted
bool IsDeleted(ctrl_t c)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:491
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
absl::container_internal::raw_hash_set::insert
insert_return_type insert(node_type &&node)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1453
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(InputIter first, InputIter last, size_t bucket_count, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1181
absl::container_internal::raw_hash_set::HashElement
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1842
xds_interop_client.int
int
Definition: xds_interop_client.py:113
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
absl::little_endian::Load64
uint64_t Load64(const void *p)
Definition: abseil-cpp/absl/base/internal/endian.h:179
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
absl::container_internal::probe_seq::index
size_t index() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:275
hpack_encoder_fixtures::Args
Args({0, 16384})
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
absl::container_internal::raw_hash_set::const_iterator::operator*
reference operator*() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1114
ABSL_INTERNAL_ASSERT_IS_FULL
#define ABSL_INTERNAL_ASSERT_IS_FULL(ctrl, msg)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:798
capacity_
uint32_t capacity_
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:132
absl::container_internal::IsNoThrowSwappable
constexpr bool IsNoThrowSwappable(std::true_type={})
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:305
absl::container_internal::Group
GroupPortableImpl Group
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:715
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
absl::container_internal::GroupPortableImpl::MaskEmptyOrDeleted
NonIterableBitMask< uint64_t, kWidth, 3 > MaskEmptyOrDeleted() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:686
absl::container_internal::IsTransparent
Definition: abseil-cpp/absl/container/internal/common.h:29
absl::container_internal::raw_hash_set::constructor
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1535
absl::container_internal::raw_hash_set::insert
void insert(std::initializer_list< T > ilist)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1445
absl::container_internal::raw_hash_set::iterator::slot_
slot_type * slot_
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1096
absl::container_internal::SanitizerUnpoisonMemoryRegion
void SanitizerUnpoisonMemoryRegion(const void *m, size_t s)
Definition: abseil-cpp/absl/container/internal/container_memory.h:230
absl::container_internal::raw_hash_set::const_iterator::operator==
friend bool operator==(const const_iterator &a, const const_iterator &b)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1123
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
absl::container_internal::raw_hash_set::const_iterator::operator++
const_iterator operator++(int)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1121
absl::container_internal::NonIterableBitMask::TrailingZeros
uint32_t TrailingZeros() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:347
absl::container_internal::ctrl_t
ctrl_t
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:422
absl::container_internal::raw_hash_set::max_load_factor
float max_load_factor() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1793
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(std::initializer_list< T > init, size_t bucket_count, const hasher &hash, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1222
absl::swap
void swap(btree_map< K, V, C, A > &x, btree_map< K, V, C, A > &y)
Definition: abseil-cpp/absl/container/btree_map.h:474
absl::container_internal::raw_hash_set::InsertSlot::s
raw_hash_set & s
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1884
absl::container_internal::raw_hash_set::emplace
std::pair< iterator, bool > emplace(Args &&... args)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1484
absl::container_internal::raw_hash_set::alloc_ref
const allocator_type & alloc_ref() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2256
absl::container_internal::raw_hash_set::infoz
HashtablezInfoHandle & infoz()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2249
absl::container_internal::IsDecomposable
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:294
testing::Eq
internal::EqMatcher< T > Eq(T x)
Definition: cares/cares/test/gmock-1.8.0/gmock/gmock.h:8561
absl::container_internal::raw_hash_set::equal_range
std::pair< iterator, iterator > equal_range(const key_arg< K > &key)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1776
absl::container_internal::hashtable_debug_internal::HashtableDebugAccess
Definition: abseil-cpp/absl/container/internal/hashtable_debug_hooks.h:49
absl::container_internal::raw_hash_set::hash_function
hasher hash_function() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1798
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
absl::container_internal::EmptyGroup
ctrl_t * EmptyGroup()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:457
absl::container_internal::BitMask::operator==
friend bool operator==(const BitMask &a, const BitMask &b)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:395
absl::container_internal::raw_hash_set::bucket_count
size_t bucket_count() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1789
absl::container_internal::raw_hash_set::iterator::operator!=
friend bool operator!=(const iterator &a, const iterator &b)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1068
absl::container_internal::BitMask::end
BitMask end() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:392
bits
OPENSSL_EXPORT ASN1_BIT_STRING * bits
Definition: x509v3.h:482
absl::container_internal::raw_hash_set::insert
iterator insert(const_iterator, T &&value)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1421
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(std::initializer_list< init_type > init, size_t bucket_count, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1235
bm_diff.diff
diff
Definition: bm_diff.py:274
extract
int extract(FILE *in, struct access *index, off_t offset, unsigned char *buf, int len)
Definition: bloaty/third_party/zlib/examples/zran.c:249
absl::container_internal::raw_hash_set::size
size_t size() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1342
absl::container_internal::NumClonedBytes
constexpr size_t NumClonedBytes()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:723
absl::compare_internal::value_type
int8_t value_type
Definition: abseil-cpp/absl/types/compare.h:45
absl::countr_zero
ABSL_INTERNAL_CONSTEXPR_CTZ std::enable_if< std::is_unsigned< T >::value, int >::type countr_zero(T x) noexcept
Definition: abseil-cpp/absl/numeric/bits.h:92
std::swap
void swap(Json::Value &a, Json::Value &b)
Specialize std::swap() for Json::Value.
Definition: third_party/bloaty/third_party/protobuf/conformance/third_party/jsoncpp/json.h:1226
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::allocator_type
std::allocator< Waker > allocator_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:951
alloc_
Alloc alloc_
Definition: abseil-cpp/absl/container/internal/container_memory_test.cc:102
absl::container_internal::ShouldInsertBackwards
bool ShouldInsertBackwards(size_t hash, const ctrl_t *ctrl)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.cc:50
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::slot_type
typename PolicyTraits::slot_type slot_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:950
absl::container_internal::hash_policy_traits::init_type
typename Policy::init_type init_type
Definition: abseil-cpp/absl/container/internal/hash_policy_traits.h:78
absl::container_internal::InsertReturnType
Definition: abseil-cpp/absl/container/internal/common.h:197
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::SlotAllocTraits
typename absl::allocator_traits< allocator_type >::template rebind_traits< slot_type > SlotAllocTraits
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:981
absl::container_internal::raw_hash_set::iterator::skip_empty_or_deleted
void skip_empty_or_deleted()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1083
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
absl::container_internal::raw_hash_set::insert
iterator insert(const_iterator, init_type &&value)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1435
absl::flags_internal::Alloc
void * Alloc(FlagOpFn op)
Definition: abseil-cpp/absl/flags/internal/flag.h:102
absl::container_internal::raw_hash_set::drop_deletes_without_resize
void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2005
absl::container_internal::raw_hash_set::EqualElement
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1851
absl::container_internal::raw_hash_set::const_iterator::difference_type
typename raw_hash_set::difference_type difference_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1108
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint-msvc2008.h:119
absl::container_internal::raw_hash_set::insert
void insert(InputIt first, InputIt last)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1440
absl::container_internal::h2_t
uint8_t h2_t
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:403
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(std::initializer_list< init_type > init, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1243
absl::container_internal::GroupPortableImpl::MaskEmpty
NonIterableBitMask< uint64_t, kWidth, 3 > MaskEmpty() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:680
absl::container_internal::CompressedTuple
Definition: abseil-cpp/absl/container/internal/compressed_tuple.h:55
b
uint64_t b
Definition: abseil-cpp/absl/container/internal/layout_test.cc:53
absl::container_internal::raw_hash_set::erase
void erase(const_iterator cit)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1594
transfer
static std::function< void(void *, Slot *, Slot *)> transfer
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:58
g
struct @717 g
absl::container_internal::H1
size_t H1(size_t hash, const ctrl_t *ctrl)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:479
absl::container_internal::raw_hash_set::operator=
raw_hash_set & operator=(raw_hash_set &&that) noexcept(absl::allocator_traits< allocator_type >::is_always_equal::value &&std::is_nothrow_move_assignable< hasher >::value &&std::is_nothrow_move_assignable< key_equal >::value)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1314
absl::container_internal::BitMask::operator*
uint32_t operator*() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:389
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::key_type
typename PolicyTraits::key_type key_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:947
F
#define F(b, c, d)
Definition: md4.c:112
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(InputIter first, InputIter last, size_t bucket_count, const hasher &hash, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1176
H
#define H(b, c, d)
Definition: md4.c:114
absl::container_internal::GroupPortableImpl::kWidth
static constexpr size_t kWidth
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:655
ABSL_DLL
#define ABSL_DLL
Definition: third_party/abseil-cpp/absl/base/config.h:746
absl::container_internal::raw_hash_set::const_iterator::reference
typename raw_hash_set::const_reference reference
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1106
ABSL_PREDICT_TRUE
#define ABSL_PREDICT_TRUE(x)
Definition: abseil-cpp/absl/base/optimization.h:181
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(std::initializer_list< T > init, size_t bucket_count, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1231
absl::bit_width
ABSL_INTERNAL_CONSTEXPR_CLZ std::enable_if< std::is_unsigned< T >::value, T >::type bit_width(T x) noexcept
Definition: abseil-cpp/absl/numeric/bits.h:135
absl::countl_zero
ABSL_INTERNAL_CONSTEXPR_CLZ std::enable_if< std::is_unsigned< T >::value, int >::type countl_zero(T x) noexcept
Definition: abseil-cpp/absl/numeric/bits.h:77
absl::container_internal::raw_hash_set::const_iterator::operator!=
friend bool operator!=(const const_iterator &a, const const_iterator &b)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1126
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::value_type
typename PolicyTraits::value_type value_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:957
absl::container_internal::raw_hash_set::begin
const_iterator begin() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1334
google_benchmark.example.empty
def empty(state)
Definition: example.py:31
Match
static bool Match(const upb_msgdef *m, const char *name, const upb_fielddef **f, const upb_oneofdef **o, const char *prefix, const char *suffix)
Definition: protobuf/ruby/ext/google/protobuf_c/message.c:195
absl::container_internal::node_handle
Definition: abseil-cpp/absl/container/internal/common.h:120
absl::container_internal::GrowthToLowerboundCapacity
size_t GrowthToLowerboundCapacity(size_t growth)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:773
absl::container_internal::AssertIsValid
void AssertIsValid(ctrl_t *ctrl)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:801
absl::container_internal::SanitizerPoisonMemoryRegion
void SanitizerPoisonMemoryRegion(const void *m, size_t s)
Definition: abseil-cpp/absl/container/internal/container_memory.h:219
absl::container_internal::EraseIf
raw_hash_set< P, H, E, A >::size_type EraseIf(Predicate &pred, raw_hash_set< P, H, E, A > *c)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2287
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(InputIter first, InputIter last, const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1186
absl::container_internal::kSentinel
@ kSentinel
Definition: bloaty/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h:263
absl::container_internal::raw_hash_set::FindElement::s
const raw_hash_set & s
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1839
absl::container_internal::raw_hash_set::iterator
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1019
absl::container_internal::raw_hash_set::extract
node_type extract(const key_arg< K > &key)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1645
mem
void * mem
Definition: libc.cpp:91
absl::container_internal::raw_hash_set::empty
bool empty() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1341
absl::container_internal::raw_hash_set::const_iterator::const_iterator
const_iterator(const ctrl_t *ctrl, const slot_type *slot)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1131
value
const char * value
Definition: hpack_parser_table.cc:165
absl::container_internal::hashtable_debug_internal
Definition: abseil-cpp/absl/container/internal/hashtable_debug_hooks.h:31
absl::container_internal::raw_hash_set::swap
void swap(raw_hash_set &that) noexcept(IsNoThrowSwappable< hasher >() &&IsNoThrowSwappable< key_equal >() &&IsNoThrowSwappable< allocator_type >(typename AllocTraits::propagate_on_container_swap{}))
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1650
absl::container_internal::IsFull
bool IsFull(ctrl_t c)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:490
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::SlotAlloc
typename absl::allocator_traits< allocator_type >::template rebind_alloc< slot_type > SlotAlloc
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:979
absl::container_internal::NonIterableBitMask::LowestBitSet
uint32_t LowestBitSet() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:337
absl::container_internal::probe_seq::offset
size_t offset() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:266
absl::container_internal::raw_hash_set::constructor::alloc_
allocator_type * alloc_
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1549
absl::void_t
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
Definition: abseil-cpp/absl/meta/type_traits.h:218
absl::container_internal::KeyArg
Definition: abseil-cpp/absl/container/internal/common.h:35
absl::container_internal::raw_hash_set::iterator::pointer
absl::remove_reference_t< reference > * pointer
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1028
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::size_type
size_t size_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:952
absl::compare_internal::eq
eq
Definition: abseil-cpp/absl/types/compare.h:72
absl::container_internal::kDeleted
@ kDeleted
Definition: bloaty/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h:262
construct
static std::function< void(void *, Slot *, Slot)> construct
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:41
key
const char * key
Definition: hpack_parser_table.cc:164
absl::container_internal::raw_hash_set::emplace_hint
iterator emplace_hint(const_iterator, Args &&... args)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1504
absl::container_internal::raw_hash_set::hash_ref
const hasher & hash_ref() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2252
ABSL_ASSUME
#define ABSL_ASSUME(cond)
Definition: abseil-cpp/absl/base/optimization.h:209
insert
static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey, upb_value val, uint32_t hash, hashfunc_t *hashfunc, eqlfunc_t *eql)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:1431
absl::container_internal::CommonAccess::Reset
static void Reset(Node *node)
Definition: abseil-cpp/absl/container/internal/common.h:180
absl::container_internal::raw_hash_set::EqualElement::rhs
const K1 & rhs
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1856
size_
size_t size_
Definition: memory_allocator.cc:56
absl::container_internal::raw_hash_set::iterator::iterator_category
std::forward_iterator_tag iterator_category
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1023
absl::container_internal::raw_hash_set::cbegin
const_iterator cbegin() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1338
absl::container_internal::raw_hash_set::prepare_insert
size_t prepare_insert(size_t hash) ABSL_ATTRIBUTE_NOINLINE
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2187
absl::container_internal::GroupPortableImpl::Match
BitMask< uint64_t, kWidth, 3 > Match(h2_t hash) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:660
absl::container_internal::SlotOffset
size_t SlotOffset(size_t capacity, size_t slot_align)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:907
absl::container_internal::raw_hash_set::constructor::slot_
slot_type ** slot_
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1550
absl::container_internal::IsEmpty
bool IsEmpty(ctrl_t c)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:489
absl::container_internal::hash_policy_traits::slot_type
typename Policy::slot_type slot_type
Definition: abseil-cpp/absl/container/internal/hash_policy_traits.h:73
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
absl::container_internal::hashtable_debug_internal::HashtableDebugAccess< Set, absl::void_t< typename Set::raw_hash_set > >::AllocatedByteSize
static size_t AllocatedByteSize(const Set &c)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2327
absl::container_internal::raw_hash_set::InsertSlot
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1873
absl::container_internal::raw_hash_set::const_iterator::pointer
typename raw_hash_set::const_pointer pointer
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1107
absl::container_internal::BitMask::mask_
T mask_
Definition: bloaty/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h:252
absl::container_internal::raw_hash_set::cend
const_iterator cend() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1339
next
AllocList * next[kMaxLevel]
Definition: abseil-cpp/absl/base/internal/low_level_alloc.cc:100
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
absl::container_internal::raw_hash_set::lazy_emplace
iterator lazy_emplace(const key_arg< K > &key, F &&f)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1554
first
StrT first
Definition: cxa_demangle.cpp:4884
absl::container_internal::raw_hash_set::iterator::operator++
iterator operator++(int)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1057
absl::container_internal::BitMask::value_type
int value_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:380
absl::container_internal::raw_hash_set::count
size_t count(const key_arg< K > &key) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1710
absl::container_internal::TrailingZeros
uint32_t TrailingZeros(T x)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:315
absl::container_internal::GroupPortableImpl::ctrl
uint64_t ctrl
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:707
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::RequiresNotInit
typename std::enable_if<!std::is_same< T, init_type >::value, int >::type RequiresNotInit
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1008
cpp.gmock_class.set
set
Definition: bloaty/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class.py:44
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::difference_type
ptrdiff_t difference_type
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:953
absl::container_internal::ConvertDeletedToEmptyAndFullToDeleted
void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t *ctrl, size_t capacity)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.cc:56
absl::container_internal::raw_hash_set::const_iterator::const_iterator
const_iterator()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1110
absl::container_internal::BitMask::operator++
BitMask & operator++()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:384
absl::container_internal::raw_hash_set::move_assign
raw_hash_set & move_assign(raw_hash_set &&that, std::true_type)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2148
absl::container_internal::NonIterableBitMask::NonIterableBitMask
NonIterableBitMask(T mask)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:332
absl::container_internal::FlatHashSetPolicy
Definition: abseil-cpp/absl/container/flat_hash_set.h:46
absl::container_internal::raw_hash_set::iterator::reference
absl::conditional_t< PolicyTraits::constant_iterators::value, const value_type &, value_type & > reference
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1027
absl::disjunction
Definition: abseil-cpp/absl/meta/type_traits.h:249
absl::container_internal::PerTableSalt
size_t PerTableSalt(const ctrl_t *ctrl)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:472
absl::container_internal::IsEmptyOrDeleted
bool IsEmptyOrDeleted(ctrl_t c)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:492
absl::container_internal::raw_hash_set::const_iterator::iterator_category
typename iterator::iterator_category iterator_category
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1104
absl::container_internal::Sample
HashtablezInfoHandle Sample(size_t inline_element_size ABSL_ATTRIBUTE_UNUSED)
Definition: abseil-cpp/absl/container/internal/hashtablez_sampler.h:251
absl::base_internal::PrefetchT0
void PrefetchT0(const void *addr)
Definition: prefetch.h:128
absl::container_internal::raw_hash_set::eq_ref
const key_equal & eq_ref() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2254
absl::container_internal::raw_hash_set::erase
iterator erase(const_iterator first, const_iterator last)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1605
absl::container_internal::raw_hash_set::hash_ref
hasher & hash_ref()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2251
absl::container_internal::raw_hash_set::destroy_slots
void destroy_slots()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1952
absl::container_internal::Alloc
Definition: abseil-cpp/absl/container/internal/hash_policy_testing.h:118
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(const allocator_type &alloc)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1163
absl::container_internal::raw_hash_set::rehash
void rehash(size_t n)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1667
absl::container_internal::raw_hash_set
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:726
absl::container_internal::raw_hash_set::reserve
void reserve(size_t n)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1689
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::hasher
absl::container_internal::hash_default_hash< Waker > hasher
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:954
absl::container_internal::raw_hash_set::const_iterator::inner_
iterator inner_
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1134
ABSL_ATTRIBUTE_REINITIALIZES
#define ABSL_ATTRIBUTE_REINITIALIZES
Definition: abseil-cpp/absl/base/attributes.h:529
absl::container_internal::raw_hash_set::const_iterator::const_iterator
const_iterator(iterator i)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1112
absl::container_internal::raw_hash_set::RequiresInsertable
typename std::enable_if< absl::disjunction< std::is_convertible< T, init_type >, SameAsElementReference< T > >::value, int >::type RequiresInsertable
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1002
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::container_internal::raw_hash_set::prefetch_heap_block
void prefetch_heap_block() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2245
absl::container_internal::raw_hash_set::EmplaceDecomposable
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1860
absl::container_internal::RequireUsableKey
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:284
absl::container_internal::kEmptyGroup
ABSL_CONST_INIT const ABSL_DLL ctrl_t kEmptyGroup[16]
Definition: abseil-cpp/absl/container/internal/raw_hash_set.cc:28
absl::container_internal::SelectBucketCountForIterRange
size_t SelectBucketCountForIterRange(InputIter first, InputIter last, size_t bucket_count)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:783
int8_t
signed char int8_t
Definition: stdint-msvc2008.h:75
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::key_equal
absl::container_internal::hash_default_eq< Waker > key_equal
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:955
absl::container_internal::GroupPortableImpl::GroupPortableImpl
GroupPortableImpl(const ctrl_t *pos)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:657
autogen_x86imm.tmp
tmp
Definition: autogen_x86imm.py:12
absl::container_internal::RequireUsableKey::operator()
std::pair< decltype(std::declval< const Hash & >)(std::declval< const PassedKey & >))), decltype(std::declval< const Eq & >)(std::declval< const ContainerKey & >), std::declval< const PassedKey & >)))> * operator()(const PassedKey &, const Args &...) const
intrin.h
absl::container_internal::NonIterableBitMask
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:330
absl::container_internal::RawHashSetTestOnlyAccess
Definition: abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc:29
setup.template
template
Definition: setup.py:47
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::key_arg
typename KeyArgImpl::template type< K, key_type > key_arg
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:970
absl::container_internal::NormalizeCapacity
size_t NormalizeCapacity(size_t n)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:744
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
generate-asm-lcov.merge
def merge(callgrind_files, srcs)
Definition: generate-asm-lcov.py:50
key_type
upb_fieldtype_t key_type
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1071
absl::container_internal::raw_hash_set::key_eq
key_equal key_eq() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1799
absl::container_internal::raw_hash_set::constructor::operator()
void operator()(Args &&... args) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1540
absl::container_internal::raw_hash_set::InsertSlot::slot
slot_type && slot
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1886
absl::container_internal::ResetCtrl
void ResetCtrl(size_t capacity, ctrl_t *ctrl, const void *slot, size_t slot_size)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:872
absl::container_internal::raw_hash_set< absl::container_internal::FlatHashSetPolicy< Waker >, absl::container_internal::hash_default_hash< Waker >, absl::container_internal::hash_default_eq< Waker >, std::allocator< Waker > >::pointer
typename absl::allocator_traits< allocator_type >::template rebind_traits< value_type >::pointer pointer
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:961
absl::container_internal::BitMask::operator!=
friend bool operator!=(const BitMask &a, const BitMask &b)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:398
regress.m
m
Definition: regress/regress.py:25
absl::container_internal::NonIterableBitMask::HighestBitSet
uint32_t HighestBitSet() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:342
absl::container_internal::raw_hash_set::EmplaceDecomposable::operator()
std::pair< iterator, bool > operator()(const K &key, Args &&... args) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1862
absl::remove_reference_t
typename std::remove_reference< T >::type remove_reference_t
Definition: abseil-cpp/absl/meta/type_traits.h:597
absl::container_internal::SetCtrl
void SetCtrl(size_t i, ctrl_t h, size_t capacity, ctrl_t *ctrl, const void *slot, size_t slot_size)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:884
absl::container_internal::raw_hash_set::rehash_and_grow_if_necessary
void rehash_and_grow_if_necessary()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2076
absl::container_internal::FindInfo::offset
size_t offset
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:810
absl::container_internal::raw_hash_set::merge
void merge(raw_hash_set< Policy, H, E, Alloc > &src)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1615
absl::container_internal::raw_hash_set::emplace_at
void emplace_at(size_t i, Args &&... args)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2211
absl::container_internal::probe_seq::offset_
size_t offset_
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:279
absl::container_internal::GroupPortableImpl::CountLeadingEmptyOrDeleted
uint32_t CountLeadingEmptyOrDeleted() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:692
absl::container_internal::SwapAlloc
void SwapAlloc(AllocType &lhs, AllocType &rhs, std::true_type)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:223
pair
std::pair< std::string, std::string > pair
Definition: abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc:78
setup.target
target
Definition: third_party/bloaty/third_party/protobuf/python/setup.py:179
absl::container_internal::raw_hash_set::swap
friend void swap(raw_hash_set &a, raw_hash_set &b) noexcept(noexcept(a.swap(b)))
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1824
absl::container_internal::raw_hash_set::iterator::operator++
iterator & operator++()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1048
absl::container_internal::raw_hash_set::max_load_factor
void max_load_factor(float)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1794
absl::container_internal::raw_hash_set::erase
void erase(iterator it)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1598
alloc
std::allocator< int > alloc
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:87
absl::container_internal::hashtable_debug_internal::HashtableDebugAccess< Set, absl::void_t< typename Set::raw_hash_set > >::Slot
typename Traits::slot_type Slot
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:2304
absl::container_internal::raw_hash_set::find
const_iterator find(const key_arg< K > &key) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1765
absl::container_internal::raw_hash_set::raw_hash_set
raw_hash_set(raw_hash_set &&that) noexcept(std::is_nothrow_copy_constructible< hasher >::value &&std::is_nothrow_copy_constructible< key_equal >::value &&std::is_nothrow_copy_constructible< allocator_type >::value)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1268
destroy
static std::function< void(void *, Slot *)> destroy
Definition: abseil-cpp/absl/container/internal/hash_policy_traits_test.cc:42
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
prefetch.h
absl::exchange
T exchange(T &obj, U &&new_value)
Definition: abseil-cpp/absl/utility/utility.h:314
absl::Hash
absl::hash_internal::Hash< T > Hash
Definition: abseil-cpp/absl/hash/hash.h:247
absl::container_internal::raw_hash_set::InsertSlot::operator()
std::pair< iterator, bool > operator()(const K &key, Args &&...) &&
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1875
absl::container_internal::raw_hash_set::capacity
size_t capacity() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1343
absl::container_internal::raw_hash_set::HashElement::operator()
size_t operator()(const K &key, Args &&...) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1844
absl::container_internal::raw_hash_set::FindElement::operator()
const_iterator operator()(const K &key, Args &&...) const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1836
absl::container_internal::raw_hash_set::~raw_hash_set
~raw_hash_set()
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:1325
absl::container_internal::NonIterableBitMask::LeadingZeros
uint32_t LeadingZeros() const
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:352
const_pointer
const typedef T * const_pointer
Definition: cxa_demangle.cpp:4833
absl::container_internal::IsValidCapacity
bool IsValidCapacity(size_t n)
Definition: abseil-cpp/absl/container/internal/raw_hash_set.h:731


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:53