MySQL 9.1.0
Source Code Documentation
|
A (partial) implementation of std::deque allocating its blocks on a MEM_ROOT. More...
#include <mem_root_deque.h>
Classes | |
struct | Block |
class | Iterator |
Public Types | |
using | size_type = size_t |
Used to conform to STL algorithm demands. More... | |
using | difference_type = ptrdiff_t |
using | value_type = Element_type |
using | pointer = Element_type * |
using | reference = Element_type & |
using | const_pointer = const Element_type * |
using | const_reference = const Element_type & |
using | iterator = Iterator< Element_type > |
using | const_iterator = Iterator< const Element_type > |
using | reverse_iterator = std::reverse_iterator< iterator > |
using | reverse_const_iterator = std::reverse_iterator< const_iterator > |
Public Member Functions | |
mem_root_deque (MEM_ROOT *mem_root) | |
Constructor. Leaves the array in an empty, valid state. More... | |
mem_root_deque (const mem_root_deque &other) | |
mem_root_deque & | operator= (const mem_root_deque &other) |
mem_root_deque (mem_root_deque &&other) | |
mem_root_deque & | operator= (mem_root_deque &&other) |
~mem_root_deque () | |
Element_type & | operator[] (size_t idx) const |
bool | push_back (const Element_type &element) |
Adds the given element to the end of the deque. More... | |
bool | push_back (Element_type &&element) |
Adds the given element to the end of the deque. More... | |
bool | push_front (const Element_type &element) |
Adds the given element to the beginning of the deque. More... | |
bool | push_front (Element_type &&element) |
Adds the given element to the end of the deque. More... | |
void | pop_back () |
Removes the last element from the deque. More... | |
void | pop_front () |
Removes the first element from the deque. More... | |
Element_type & | front () |
Returns the first element in the deque. More... | |
const Element_type & | front () const |
Element_type & | back () |
Returns the last element in the deque. More... | |
const Element_type & | back () const |
void | clear () |
Removes all elements from the deque. More... | |
iterator | begin () |
iterator | end () |
reverse_iterator | rbegin () |
reverse_iterator | rend () |
const_iterator | cbegin () |
const_iterator | cend () |
const_iterator | begin () const |
const_iterator | end () const |
reverse_const_iterator | crbegin () const |
reverse_const_iterator | crend () const |
reverse_const_iterator | rbegin () const |
reverse_const_iterator | rend () const |
size_t | size () const |
bool | empty () const |
iterator | erase (const_iterator first, const_iterator last) |
Erase all the elements in the specified range. More... | |
iterator | erase (const_iterator position) |
Removes a single element from the array. More... | |
iterator | insert (const_iterator pos, const Element_type &value) |
Insert an element at a given position. More... | |
iterator | insert (const_iterator pos, Element_type &&value) |
Insert an element at a given position. More... | |
template<class ForwardIt > | |
iterator | insert (const_iterator pos, ForwardIt first, ForwardIt last) |
Private Member Functions | |
void | invalidate_iterators () |
bool | add_initial_block () |
Adds the first block of elements. More... | |
bool | add_block_back () |
bool | add_block_front () |
size_t | num_blocks () const |
Element_type & | get (size_t physical_idx) const |
Gets a reference to the memory used to store an element with the given physical index, starting from zero. More... | |
size_t | generation () const |
Private Attributes | |
Block * | m_blocks = nullptr |
Pointer to the first block. More... | |
size_t | m_begin_idx = 0 |
Physical index to the first valid element. More... | |
size_t | m_end_idx = 0 |
Physical index one past the last valid element. More... | |
size_t | m_capacity = 0 |
Number of blocks, multiplied by block_elements. More... | |
MEM_ROOT * | m_root |
Pointer to the MEM_ROOT that we store our blocks and elements on. More... | |
size_t | m_generation = 0 |
Incremented each time we make an operation that would invalidate iterators. More... | |
Static Private Attributes | |
static constexpr size_t | block_elements = FindElementsPerBlock<Element_type>() |
Number of elements in each block. More... | |
A (partial) implementation of std::deque allocating its blocks on a MEM_ROOT.
This class works pretty much like an std::deque with a Mem_root_allocator, and used to be a forwarder to it. However, libstdc++ has a very complicated implementation of std::deque, leading to code blowup (e.g., operator[] is 23 instructions on x86-64, including two branches), and we cannot easily use libc++ on all platforms. This version is instead:
It gives mostly the same guarantees as std::deque; elements can be inserted efficiently on both front and back [1]. {push,pop}_{front,back} guarantees reference stability except for to removed elements (obviously), and invalidates iterators. (Iterators are forcefully invalidated using asserts.) erase() does the same. Note that unlike std::deque, insert() at begin() will invalidate references. Some functionality, like several constructors, resize(), shrink_to_fit(), swap(), etc. is missing.
The implementation is the same as classic std::deque: Elements are held in blocks of about 1 kB each. Once an element is in a block, it never moves (giving the aforementioned pointer stability). The blocks are held in an array, which can be reallocated when more blocks are needed. The implementation keeps track of the used items in terms of “physical indexes”; element 0 starts at the first byte of the first block, element 1 starts immediately after 0, and so on. So you can have something like (assuming very small blocks of only 4 elements each for the sake of drawing):
block 0 block 1 block 2 ↓ ↓ ↓ [x x 2 3] [4 5 6 7] [8 9 x x] ↑ ↑ begin_idx = 2 end_idx = 10
end_idx counts as is customary one-past-the-end, so in this case, the elements [2,9) would be valid, and e.g. (*this)[4] would give physical index 6, which points to the third element (index 2) in the middle block (block 1). Inserting a new element at the front is as easy as putting it in physical index 1 and adjusting begin_idx to the left. This means a lookup by index requires some shifting, masking and a double indirect load.
Iterators keep track of which deque they belong to, and what physical index they point to. (So lookup by iterator also requires a double indirect load, but the alternative would be caching the block pointer and having an extra branch when advancing the iterator.) Inserting a new block at the beginning would move around all the physical indexes (which is why iterators get invalidated; we could probably get around this by having an “offset to first block”, but it's likely not worth it.)
[1] Actually, it's O(n), since there's no exponential growth of the blocks array. But the blocks are reallocated very rarely, so it is generally efficient nevertheless.
using mem_root_deque< Element_type >::const_iterator = Iterator<const Element_type> |
using mem_root_deque< Element_type >::const_pointer = const Element_type * |
using mem_root_deque< Element_type >::const_reference = const Element_type & |
using mem_root_deque< Element_type >::difference_type = ptrdiff_t |
using mem_root_deque< Element_type >::iterator = Iterator<Element_type> |
using mem_root_deque< Element_type >::pointer = Element_type * |
using mem_root_deque< Element_type >::reference = Element_type & |
using mem_root_deque< Element_type >::reverse_const_iterator = std::reverse_iterator<const_iterator> |
using mem_root_deque< Element_type >::reverse_iterator = std::reverse_iterator<iterator> |
using mem_root_deque< Element_type >::size_type = size_t |
Used to conform to STL algorithm demands.
using mem_root_deque< Element_type >::value_type = Element_type |
|
inlineexplicit |
Constructor. Leaves the array in an empty, valid state.
|
inline |
|
inline |
|
inline |
|
private |
|
private |
|
inlineprivate |
Adds the first block of elements.
|
inline |
Returns the last element in the deque.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Removes all elements from the deque.
Destructors are called, but since the elements themselves are allocated on the MEM_ROOT, their memory cannot be freed.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Erase all the elements in the specified range.
first | iterator that points to the first element to remove |
last | iterator that points to the element after the last one to remove |
|
inline |
Removes a single element from the array.
position | iterator that points to the element to remove |
|
inline |
Returns the first element in the deque.
|
inline |
|
inlineprivate |
|
inlineprivate |
Gets a reference to the memory used to store an element with the given physical index, starting from zero.
Note that block_elements is always a power of two, so the division and modulus operations are cheap.
|
inline |
Insert an element at a given position.
The element is a copy of the given one.
pos | the new element is inserted before the element at this position |
value | the value of the new element |
|
inline |
Insert an element at a given position.
The element is moved into place.
pos | the new element is inserted before the element at this position |
value | the value of the new element |
|
inline |
|
inlineprivate |
|
inlineprivate |
|
inline |
|
inline |
|
inline |
|
inline |
Removes the last element from the deque.
|
inline |
Removes the first element from the deque.
|
inline |
Adds the given element to the end of the deque.
The element is a copy of the given one.
|
inline |
Adds the given element to the end of the deque.
The element is moved into place.
|
inline |
Adds the given element to the beginning of the deque.
The element is a copy of the given one.
|
inline |
Adds the given element to the end of the deque.
The element is moved into place.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
staticconstexprprivate |
Number of elements in each block.
|
private |
Physical index to the first valid element.
|
private |
Pointer to the first block.
Can be nullptr if there are no elements (this makes the constructor cheaper). Stored on the MEM_ROOT, and needs no destruction, so just a raw pointer.
|
private |
Number of blocks, multiplied by block_elements.
(Storing this instead of the number of blocks itself makes testing in push_back cheaper.)
|
private |
Physical index one past the last valid element.
If begin == end, the array is empty (and then it doesn't matter what the values are).
|
private |
Incremented each time we make an operation that would invalidate iterators.
Asserts use this value in debug mode to be able to verify that they have not been invalidated. (In optimized mode, using an invalidated iterator incurs undefined behavior.)
|
private |
Pointer to the MEM_ROOT that we store our blocks and elements on.