MySQL 8.0.37
Source Code Documentation
overflow_bitset.h
Go to the documentation of this file.
1/* Copyright (c) 2021, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef SQL_JOIN_OPTIMIZER_OVERFLOW_BITSET_H
25#define SQL_JOIN_OPTIMIZER_OVERFLOW_BITSET_H
26
27/**
28 @file
29
30 OverflowBitset is a fixed-size (once allocated) bitmap that is optimized for
31 the common case of few elements, yet can support an arbitrary number.
32 For 63 bits or fewer, it fits into a simple 64-bit machine word; for more,
33 it instead “overflows” to a pointer to externally-allocated storage
34 (typically on a MEM_ROOT). In other words, one loses only 1 bit for the common
35 (small) case. For small (“inline”) bit sets, most operations are simple
36 bit-twiddling operations, adding only a small and easily-predicatable test to
37 each of them.
38
39 This is possible because a pointer to external storage of 64-bit values
40 will (must) be aligned to 8 bytes, so the lowest bit of the address
41 cannot be 1. We can use this to distinguish between inline and non-inline
42 sets.
43
44 There are two classes: OverflowBitset is an immutable (const) bitset with
45 value semantics; it can be freely assigned, copied, stored in AccessPath
46 (which also has value semantics), etc. with no worries, but not modified.
47 (The storage is never freed; it is presumed to live on a MEM_ROOT.)
48 MutableOverflowBitset can be modified, but it is move-only; this avoids
49 the problem where one takes a copy of a (non-inline) bit set and then
50 modify one of them, not expecting that modification to also affect
51 the other one. (Ie., it avoids the design mistake in String, where the
52 copy constructor unexpectedly can become a shallow copy, but not always.)
53 MutableOverflowBitset can be converted to OverflowBitset by means of a
54 move, at which point it is effectively frozen and cannot be changed further.
55
56 For simplicity, most operations over OverflowBitset require the two
57 bit sets to be of the same size. The exception is that an all-zero inline
58 bit set can be tested against others in Overlaps(); this is useful so that we
59 don't need to initialize bit sets in AccessPath that never have any filters
60 set (the default constructor makes them inline and all-zero).
61 */
62
63#include <assert.h>
64#include <limits.h>
65#include <stddef.h>
66#include <stdint.h>
67#include <string.h>
68
69#include <array>
70#include <tuple>
71
72#include "my_alloc.h"
74
76
78 public:
79 // Default is to zero-initialize.
81
82 explicit OverflowBitset(uint32_t bits) : m_bits((uintptr_t{bits} << 1) | 1) {
83 // Check that we didn't overflow on 32-bit platforms.
84 assert((m_bits >> 1) == bits);
85 }
86
87 // Reset the entire bitset to an inline all-zero bitset.
88 // This is distinct from ClearBits(), which only clears a given number
89 // of bits, and does not change the capacity.
90 void Clear() { m_bits = 1; }
91
92 // Value semantics, so:
93 OverflowBitset(const OverflowBitset &) = default;
97
98 // Can move-convert MutableOverflowBitset into OverflowBitset.
101
102 bool is_inline() const { return m_bits & 1; }
103 bool empty() { return m_bits == 1; }
104
105 size_t capacity() const {
106 if (is_inline()) {
107 return kInlineBits;
108 } else {
109 return m_ext->m_num_blocks * sizeof(uint64_t) * CHAR_BIT;
110 }
111 }
112
114
115 bool IsContainedIn(const MEM_ROOT *mem_root) const {
116 return !is_inline() && mem_root->Contains(m_ext);
117 }
118
119 // NOTE: These could also be made to take in MutableOverflowBitset(),
120 // simply by templating them (due to the private inheritance).
127
128 protected:
129 struct Ext {
131 uint64_t m_bits[1];
132 };
133 static_assert(alignof(Ext) % 2 == 0, "The lowest bit must be zero.");
134
135 union {
136 uint64_t m_bits; // Lowest bit must be 1.
138 };
139 static constexpr int kInlineBits = sizeof(m_bits) * CHAR_BIT - 1;
140
141 void InitOverflow(MEM_ROOT *mem_root, size_t capacity);
148
149 friend bool Overlaps(OverflowBitset a, OverflowBitset b);
151 friend bool IsSubset(OverflowBitset a, OverflowBitset b);
153 friend bool IsBitSet(int bit_num, OverflowBitset x);
154 friend bool IsBitSetOverflow(int bit_num, OverflowBitset x);
155 friend bool IsEmpty(OverflowBitset x);
156 friend int PopulationCount(OverflowBitset x);
158 template <size_t N, class Combine>
161};
162static_assert(
163 sizeof(OverflowBitset) <= sizeof(uint64_t),
164 "OverflowBitset is intended to be as compact as a regular 64-bit set.");
165
166// Private inheritance, so that the only way of converting to OverflowBitset
167// for external callers is by a move-convert.
169 public:
170 // NOTE: Will round up the given capacity to either 31/63 (for anything
171 // smaller than 32/64), or to the next multiple of 64 (for anything else).
173 if (capacity <= kInlineBits) {
174 m_bits = 1;
175 } else {
177 }
178 }
179
180 // Move-only, so that we don't inadvertently modify aliases.
184 m_bits = other.m_bits;
185 other.m_bits = 1;
186 }
188 m_bits = other.m_bits;
189 other.m_bits = 1;
190 return *this;
191 }
192
193 void SetBit(int bit_num) {
194 assert(bit_num >= 0);
195 assert(static_cast<size_t>(bit_num) < capacity());
196 const unsigned bn = bit_num; // To avoid sign extension taking time.
197 if (is_inline()) {
198 assert(bit_num < 63);
199 m_bits |= uint64_t{1} << (bn + 1);
200 } else {
201 m_ext->m_bits[bn / 64] |= uint64_t{1} << (bn % 64);
202 }
203 }
204
205 void ClearBits(int begin_bit_num, int end_bit_num) {
206 assert(begin_bit_num >= 0);
207 assert(end_bit_num >= 0);
208 assert(begin_bit_num <= end_bit_num);
209 assert(static_cast<size_t>(begin_bit_num) <= capacity());
210 assert(static_cast<size_t>(end_bit_num) <= capacity());
211 if (is_inline()) {
212 m_bits &= ~BitsBetween(begin_bit_num + 1, end_bit_num + 1);
213 } else {
214 ClearBitsOverflow(begin_bit_num, end_bit_num);
215 }
216 }
217
218 inline void ClearBit(int bit_num) {
219 // TODO: Consider a more specialized version here if it starts
220 // showing up in the profiles.
221 ClearBits(bit_num, bit_num + 1);
222 }
223
226 }
227
228 private:
229 friend bool IsBitSet(int bit_num, const MutableOverflowBitset &x);
230 friend bool Overlaps(OverflowBitset a, const MutableOverflowBitset &b);
231 friend bool Overlaps(const MutableOverflowBitset &a,
232 const MutableOverflowBitset &b);
233 friend bool Overlaps(const MutableOverflowBitset &a, OverflowBitset b);
234 friend bool IsSubset(OverflowBitset a, const MutableOverflowBitset &b);
235 friend bool IsSubset(const MutableOverflowBitset &a,
236 const MutableOverflowBitset &b);
237 friend bool IsSubset(const MutableOverflowBitset &a, OverflowBitset b);
238 friend bool IsEmpty(const MutableOverflowBitset &x);
239 friend int PopulationCount(const MutableOverflowBitset &x);
240 void SetBitOverflow(int bit_num);
241 void ClearBitsOverflow(int begin_bit_num, int end_bit_num);
242
243 friend class OverflowBitset;
244};
245
247 m_bits = other.m_bits;
248 other.m_bits = 1;
249}
250
252 MutableOverflowBitset &&other) {
253 m_bits = other.m_bits;
254 other.m_bits = 1;
255 return *this;
256}
257
260 if (is_inline()) {
261 ret.m_bits = m_bits;
262 } else {
263 memcpy(ret.m_ext, m_ext,
264 sizeof(m_ext->m_num_blocks) +
265 m_ext->m_num_blocks * sizeof(m_ext->m_bits));
266 }
267 return ret;
268}
269
272 OverflowBitset b) {
273 assert(a.is_inline() == b.is_inline());
274 assert(a.capacity() == b.capacity());
275 if (a.is_inline()) {
277 ret.m_bits = a.m_bits | b.m_bits;
278 return ret;
279 } else {
280 return OrOverflow(mem_root, a, b);
281 }
282}
283
286 OverflowBitset b) {
287 assert(a.is_inline() == b.is_inline());
288 assert(a.capacity() == b.capacity());
289 if (a.is_inline()) {
291 ret.m_bits = a.m_bits & b.m_bits;
292 return ret;
293 } else {
294 return AndOverflow(mem_root, a, b);
295 }
296}
297
300 OverflowBitset b) {
301 assert(a.is_inline() == b.is_inline());
302 assert(a.capacity() == b.capacity());
303 if (a.is_inline()) {
305 ret.m_bits = (a.m_bits ^ b.m_bits) | 1;
306 return ret;
307 } else {
308 return XorOverflow(mem_root, a, b);
309 }
310}
311
312// Definitions overloading utility functions in bit_utils.h, making it generally
313// possible to use OverflowBitset as we use regular uint64_t bitsets
314// (e.g. NodeMap).
315//
316// Since one cannot easily combine non-inline OverflowBitsets without allocating
317// memory, the BitsSetIn() overload supports combining state as-we-go.
318// For instance, where you would normally write (for uint64_t)
319//
320// for (int bit_idx : BitsSetIn(x & y))
321//
322// you would use this variation for OverflowBitsets:
323//
324// for (int bit_idx : BitsSetInBoth(x, y))
325//
326// Under the hood, BitsSetInBoth() calls a Combine functor that ANDs the two
327// uint64_t bitwise (for inline bitsets only once, but for overflow bitsets
328// multiple times, on-demand as we iterate), which can potentially save
329// on a lot of bitscan operations and loop iterations versus trying to test
330// one-by-one. This can be extended to any number of arguments.
331//
332// Combine::operator() must be const, Combine must be movable (but can have
333// state).
334
335template <size_t N, class Combine>
337 public:
338 class iterator {
339 private:
340 const Combine *m_combine;
341 uint64_t m_state;
342
343 // m_next holds, for each bitset array, the pointer to the next
344 // uint64_t to be processed/read (once m_state is zero, ie.,
345 // there are no more bits in the current state). When m_next[0] == m_end,
346 // iteration is over. For inline bitsets, m_next[0] == m_end == nullptr,
347 // so once the first 64-bit group is processed, we are done.
348 // (We assume all arrays have the same length, so we only need one
349 // end pointer.)
350 std::array<const uint64_t *, N> m_next;
351 const uint64_t *const m_end;
353
354 public:
355 // For inline bitsets.
356 iterator(uint64_t state, const Combine *combine)
357 : m_combine(combine), m_state(state), m_end(nullptr), m_base(0) {
358 m_next[0] = nullptr;
359 }
360
361 // For overflow bitsets.
362 iterator(const std::array<const uint64_t *, N> begin, const uint64_t *end,
363 const Combine *combine)
364 : m_combine(combine),
365 m_state(0),
366 m_next(begin),
367 m_end(end),
368 m_base(-64) {
369 while (m_state == 0 && m_next[0] != m_end) {
371 for (size_t i = 0; i < N; ++i) {
372 ++m_next[i];
373 }
374 m_base += 64;
375 }
376 }
377
378 bool operator==(const iterator &other) const {
379 assert(m_end == other.m_end);
380 return m_state == other.m_state && m_next[0] == other.m_next[0];
381 }
382 bool operator!=(const iterator &other) const {
383 assert(m_end == other.m_end);
384 return m_state != other.m_state || m_next[0] != other.m_next[0];
385 }
386 size_t operator*() const { return FindLowestBitSet(m_state) + m_base; }
388 // Clear the lowest set bit.
389 assert(m_state != 0);
390 m_state = m_state & (m_state - 1);
391
392 while (m_state == 0 && m_next[0] != m_end) {
394 for (size_t i = 0; i < N; ++i) {
395 ++m_next[i];
396 }
397 m_base += 64;
398 }
399 return *this;
400 }
401 };
402
403 OverflowBitsetBitsIn(std::array<OverflowBitset, N> bitsets, Combine combine)
404 : m_bitsets(bitsets), m_combine(std::move(combine)) {}
405
406 iterator begin() const {
407 if (m_bitsets[0].is_inline()) {
408 std::array<uint64_t, N> bits;
409 for (size_t i = 0; i < N; ++i) {
410 assert(m_bitsets[i].is_inline());
411 bits[i] = m_bitsets[i].m_bits;
412 }
413 uint64_t state = std::apply(m_combine, bits);
414 return iterator{state >> 1, &m_combine};
415 } else {
416 std::array<const uint64_t *, N> ptrs;
417 for (size_t i = 0; i < N; ++i) {
418 assert(!m_bitsets[i].is_inline());
419 assert(m_bitsets[i].capacity() == m_bitsets[0].capacity());
420 ptrs[i] = m_bitsets[i].m_ext->m_bits;
421 }
422 const uint64_t *end =
423 m_bitsets[0].m_ext->m_bits + m_bitsets[0].m_ext->m_num_blocks;
424 return iterator{ptrs, end, &m_combine};
425 }
426 }
427 iterator end() const {
428 if (m_bitsets[0].is_inline()) {
429 return iterator{0, &m_combine};
430 } else {
431 std::array<const uint64_t *, N> ptrs;
432 for (size_t i = 0; i < N; ++i) {
433 assert(m_bitsets[i].is_inline() == m_bitsets[0].is_inline());
434 assert(m_bitsets[i].capacity() == m_bitsets[0].capacity());
435 ptrs[i] = m_bitsets[i].m_ext->m_bits + m_bitsets[i].m_ext->m_num_blocks;
436 }
437 return iterator{ptrs, ptrs[0], &m_combine};
438 }
439 }
440
441 private:
442 static inline uint64_t ReadAndCombine(
443 const std::array<const uint64_t *, N> &ptrs, const Combine *combine) {
444 std::array<uint64_t, N> bits;
445 for (size_t i = 0; i < N; ++i) {
446 bits[i] = *ptrs[i];
447 }
448 return std::apply(*combine, bits);
449 }
450
451 const std::array<OverflowBitset, N> m_bitsets;
452 const Combine m_combine;
453};
454
456 uint64_t operator()(uint64_t x) const { return x; }
457};
458inline auto BitsSetIn(OverflowBitset bitset) {
460}
461
463 uint64_t operator()(uint64_t x, uint64_t y) const { return x & y; }
464};
465inline auto BitsSetInBoth(OverflowBitset bitset_a, OverflowBitset bitset_b) {
466 return OverflowBitsetBitsIn<2, AndCombine>{{bitset_a, bitset_b},
467 AndCombine()};
468}
469
471
473 if (a.m_bits == 1 || b.m_bits == 1) {
474 // Empty and inline, so nothing overlaps.
475 // This is a special case that does not require the two
476 // sets to be of the same size (see file comment).
477 return false;
478 }
479 assert(a.is_inline() == b.is_inline());
480 assert(a.capacity() == b.capacity());
481 if (a.is_inline()) {
482 return (a.m_bits & b.m_bits) != 1;
483 } else {
484 return OverlapsOverflow(a, b);
485 }
486}
487
489 return Overlaps(a, static_cast<const OverflowBitset &>(b));
490}
491
492inline bool Overlaps(const MutableOverflowBitset &a,
493 const MutableOverflowBitset &b) {
494 return Overlaps(static_cast<const OverflowBitset &>(a),
495 static_cast<const OverflowBitset &>(b));
496}
497
499 return Overlaps(static_cast<const OverflowBitset &>(a), b);
500}
501
503 assert(a.is_inline() == b.is_inline());
504 assert(a.capacity() == b.capacity());
505 if (a.is_inline()) {
506 return IsSubset(a.m_bits, b.m_bits);
507 } else {
508 return IsSubsetOverflow(a, b);
509 }
510}
511
512inline bool IsBitSet(int bit_num, OverflowBitset x) {
513 assert(bit_num >= 0);
514 assert(static_cast<size_t>(bit_num) < x.capacity());
515 const unsigned bn = bit_num; // To avoid sign extension taking time.
516 if (x.is_inline()) {
517 return Overlaps(x.m_bits, uint64_t{1} << (bn + 1));
518 } else {
519 return Overlaps(x.m_ext->m_bits[bn / 64], uint64_t{1} << (bn % 64));
520 }
521}
522
523inline bool IsBitSet(int bit_num, const MutableOverflowBitset &x) {
524 return IsBitSet(bit_num, static_cast<const OverflowBitset &>(x));
525}
526
528 return IsSubset(a, static_cast<const OverflowBitset &>(b));
529}
530
531inline bool IsSubset(const MutableOverflowBitset &a,
532 const MutableOverflowBitset &b) {
533 return IsSubset(static_cast<const OverflowBitset &>(a),
534 static_cast<const OverflowBitset &>(b));
535}
536
538 return IsSubset(static_cast<const OverflowBitset &>(a), b);
539}
540
541// This is mostly used to guard a few asserts, so it's better that it's
542// completely visible, so that the compiler can remove it totally
543// in optimized mode.
544inline bool IsEmpty(OverflowBitset x) {
545 if (x.is_inline()) {
546 return x.m_bits == 1;
547 } else {
548 for (unsigned i = 0; i < x.m_ext->m_num_blocks; ++i) {
549 if (x.m_ext->m_bits[i] != 0) {
550 return false;
551 }
552 }
553 return true;
554 }
555}
556
557inline bool IsEmpty(const MutableOverflowBitset &x) {
558 return IsEmpty(static_cast<const OverflowBitset &>(x));
559}
560
562 if (x.is_inline()) {
563 return PopulationCount(x.m_bits) - 1;
564 } else {
565 return PopulationCountOverflow(x);
566 }
567}
568
569/// Find the nuber of bits set in 'x'.
571 return PopulationCount(static_cast<const OverflowBitset &>(x));
572}
573
574#endif // SQL_JOIN_OPTIMIZER_OVERFLOW_BITSET_H
size_t FindLowestBitSet(uint64_t x)
Definition: bit_utils.h:71
Definition: overflow_bitset.h:168
void ClearBits(int begin_bit_num, int end_bit_num)
Definition: overflow_bitset.h:205
MutableOverflowBitset(MutableOverflowBitset &&other)
Definition: overflow_bitset.h:183
friend int PopulationCount(const MutableOverflowBitset &x)
Find the nuber of bits set in 'x'.
Definition: overflow_bitset.h:570
friend bool IsBitSet(int bit_num, const MutableOverflowBitset &x)
Definition: overflow_bitset.h:523
void ClearBitsOverflow(int begin_bit_num, int end_bit_num)
Definition: overflow_bitset.cc:80
void SetBit(int bit_num)
Definition: overflow_bitset.h:193
friend bool IsSubset(OverflowBitset a, const MutableOverflowBitset &b)
Definition: overflow_bitset.h:527
MutableOverflowBitset & operator=(const MutableOverflowBitset &)=delete
friend bool Overlaps(OverflowBitset a, const MutableOverflowBitset &b)
Definition: overflow_bitset.h:488
MutableOverflowBitset(MEM_ROOT *mem_root, size_t capacity)
Definition: overflow_bitset.h:172
friend class OverflowBitset
Definition: overflow_bitset.h:243
friend bool IsEmpty(const MutableOverflowBitset &x)
Definition: overflow_bitset.h:557
MutableOverflowBitset(const MutableOverflowBitset &)=delete
void SetBitOverflow(int bit_num)
MutableOverflowBitset & operator=(MutableOverflowBitset &&other)
Definition: overflow_bitset.h:187
void ClearBit(int bit_num)
Definition: overflow_bitset.h:218
MutableOverflowBitset Clone(MEM_ROOT *mem_root) const
Definition: overflow_bitset.h:224
Definition: overflow_bitset.h:338
const Combine * m_combine
Definition: overflow_bitset.h:340
bool operator==(const iterator &other) const
Definition: overflow_bitset.h:378
iterator(uint64_t state, const Combine *combine)
Definition: overflow_bitset.h:356
size_t operator*() const
Definition: overflow_bitset.h:386
iterator(const std::array< const uint64_t *, N > begin, const uint64_t *end, const Combine *combine)
Definition: overflow_bitset.h:362
bool operator!=(const iterator &other) const
Definition: overflow_bitset.h:382
std::array< const uint64_t *, N > m_next
Definition: overflow_bitset.h:350
const uint64_t *const m_end
Definition: overflow_bitset.h:351
int m_base
Definition: overflow_bitset.h:352
iterator & operator++()
Definition: overflow_bitset.h:387
uint64_t m_state
Definition: overflow_bitset.h:341
Definition: overflow_bitset.h:336
iterator end() const
Definition: overflow_bitset.h:427
static uint64_t ReadAndCombine(const std::array< const uint64_t *, N > &ptrs, const Combine *combine)
Definition: overflow_bitset.h:442
iterator begin() const
Definition: overflow_bitset.h:406
const std::array< OverflowBitset, N > m_bitsets
Definition: overflow_bitset.h:451
const Combine m_combine
Definition: overflow_bitset.h:452
OverflowBitsetBitsIn(std::array< OverflowBitset, N > bitsets, Combine combine)
Definition: overflow_bitset.h:403
Definition: overflow_bitset.h:77
friend bool IsSubset(OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.h:502
bool IsContainedIn(const MEM_ROOT *mem_root) const
Definition: overflow_bitset.h:115
static MutableOverflowBitset Or(MEM_ROOT *mem_root, OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.h:270
friend int PopulationCountOverflow(OverflowBitset x)
Definition: overflow_bitset.cc:138
friend bool Overlaps(OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.h:472
OverflowBitset()
Definition: overflow_bitset.h:80
static MutableOverflowBitset OrOverflow(MEM_ROOT *mem_root, OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.cc:41
friend bool IsSubsetOverflow(OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.cc:126
friend int PopulationCount(OverflowBitset x)
Definition: overflow_bitset.h:561
MutableOverflowBitset Clone(MEM_ROOT *mem_root) const
Definition: overflow_bitset.h:258
size_t capacity() const
Definition: overflow_bitset.h:105
static constexpr int kInlineBits
Definition: overflow_bitset.h:139
bool empty()
Definition: overflow_bitset.h:103
OverflowBitset & operator=(const OverflowBitset &)=default
bool is_inline() const
Definition: overflow_bitset.h:102
static MutableOverflowBitset XorOverflow(MEM_ROOT *mem_root, OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.cc:67
friend bool OverlapsOverflow(OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.cc:114
static MutableOverflowBitset AndOverflow(MEM_ROOT *mem_root, OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.cc:54
uint64_t m_bits
Definition: overflow_bitset.h:136
OverflowBitset(const OverflowBitset &)=default
friend bool IsBitSetOverflow(int bit_num, OverflowBitset x)
friend bool IsEmpty(OverflowBitset x)
Definition: overflow_bitset.h:544
static MutableOverflowBitset And(MEM_ROOT *mem_root, OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.h:284
OverflowBitset(uint32_t bits)
Definition: overflow_bitset.h:82
OverflowBitset(OverflowBitset &&)=default
Ext * m_ext
Definition: overflow_bitset.h:137
static MutableOverflowBitset Xor(MEM_ROOT *mem_root, OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.h:298
void InitOverflow(MEM_ROOT *mem_root, size_t capacity)
Definition: overflow_bitset.cc:32
friend bool IsBitSet(int bit_num, OverflowBitset x)
Definition: overflow_bitset.h:512
void Clear()
Definition: overflow_bitset.h:90
OverflowBitset & operator=(OverflowBitset &&)=default
static MEM_ROOT mem_root
Definition: client_plugin.cc:110
Fido Client Authentication nullptr
Definition: fido_client_plugin.cc:222
This file follows Google coding style, except for the name MEM_ROOT (which is kept for historical rea...
std::atomic< Type > N
Definition: ut0counter.h:225
Definition: gcs_xcom_synode.h:64
int PopulationCountOverflow(OverflowBitset x)
Definition: overflow_bitset.cc:138
bool IsSubsetOverflow(OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.cc:126
bool IsSubset(OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.h:502
bool Overlaps(OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.h:472
auto BitsSetInBoth(OverflowBitset bitset_a, OverflowBitset bitset_b)
Definition: overflow_bitset.h:465
int PopulationCount(OverflowBitset x)
Definition: overflow_bitset.h:561
bool OverlapsOverflow(OverflowBitset a, OverflowBitset b)
Definition: overflow_bitset.cc:114
auto BitsSetIn(OverflowBitset bitset)
Definition: overflow_bitset.h:458
bool IsEmpty(OverflowBitset x)
Definition: overflow_bitset.h:544
bool IsBitSet(int bit_num, OverflowBitset x)
Definition: overflow_bitset.h:512
Definition: overflow_bitset.h:462
uint64_t operator()(uint64_t x, uint64_t y) const
Definition: overflow_bitset.h:463
Definition: overflow_bitset.h:455
uint64_t operator()(uint64_t x) const
Definition: overflow_bitset.h:456
The MEM_ROOT is a simple arena, where allocations are carved out of larger blocks.
Definition: my_alloc.h:83
bool Contains(void *ptr) const
Returns whether this MEM_ROOT contains the given pointer, ie., whether it was given back from Alloc(n...
Definition: my_alloc.h:353
Definition: overflow_bitset.h:129
uint64_t m_bits[1]
Definition: overflow_bitset.h:131
size_t m_num_blocks
Definition: overflow_bitset.h:130