General Utility Library for C++14
2.11
|
A circular data buffer of (semi-)fixed capacity to which elements can be added at the front or at the back.
A SlidingBuffer is a flat array containing zero to capacity() elements of an arbitrary type. The capacity can either be specified at compile time via a template parameter or at runtime via resize(). In the former case, the internal buffer is embedded in the object (std::array), in the latter case it is dynamically allocated (std::vector).
The SlidingBuffer shares many characteristics with traditional ring buffers: It has a fixed maximum size and new elements are added with push_front() or push_back(). If this is done when the buffer is filled() to capacity, an element automatically drops out at the other end of the sliding window:
This buffer is not intended for producer-consumer problems. If the elements access is atomic it is thread-safe though. All auxiliary functions that mutate the data are not thread safe.
Differing from arrays this buffer will start empty (with a size of zero). Once the buffer has grown to its designated size (i.e. capacity), its size() only changes if clear(), pop_front(), or pop_back() are used.
A typical application would be to analyze an incoming stream of elements in a finite impulse response filter.
This container uses an accompanying iterator class called SlidingBufferIterator. See SlidingBufferExposed for a variant with a different (more performant) iterator interface.
Iterator invalidation is specified at SlidingBufferIterator.
The sliding buffer can be instantiated in two slightly different versions:
fixed_capacity
template parameter. The elements are stored within the sliding buffer as in a std::array.fixed_capacity
can be omitted. It defaults to zero, and space for elements can subsequently be allocated dynamically as in a std::vector. You need to use a constructor that sets a certain capacity or set the capacity afterwards with resize(). As long as the capacity is zero, the buffer is unusable and most operations result in undefined behavior.ElementT
must be default constructible.
ElementT | Type of elements in the buffer |
fixed_capacity | Maximum number of elements in the buffer (capacity), zero if unspecified/dynamic |
Container | Type of the underlying container, usually not specified |
#include <SlidingBuffer.h>
Classes | |
class | SlidingBufferIterator |
Iterator of the SlidingBuffer container. More... | |
Public Types | |
using | container_type = Container |
Type of the underlying container (e.g. std::array<value_type, ..>) | |
using | value_type = ElementT |
Type of the elements in the underlying container. | |
using | size_type = typename Container::size_type |
Unsigned integer type (usually std::size_t) | |
using | difference_type = typename Container::difference_type |
Signed integer type (usually std::ptrdiff_t) | |
using | reference = typename Container::reference |
Reference to an element. | |
using | const_reference = typename Container::const_reference |
Reference to a constant element. | |
using | pointer = typename Container::pointer |
Pointer to an element. | |
using | const_pointer = typename Container::const_pointer |
Pointer to a constant element. | |
using | iterator = SlidingBufferIterator< SlidingBuffer< ElementT, fixed_capacity, Container > * > |
Iterator to an element. | |
using | const_iterator = SlidingBufferIterator< SlidingBuffer< ElementT, fixed_capacity, Container > const * > |
Iterator to a const element. | |
using | reverse_iterator = std::reverse_iterator< iterator > |
Iterator to an element in reversed container. | |
using | const_reverse_iterator = std::reverse_iterator< const_iterator > |
Iterator to a const element in reversed container. | |
Public Member Functions | |
SlidingBuffer ()=default | |
Construct an empty sliding buffer. More... | |
SlidingBuffer (SlidingBuffer const &)=default | |
Default copy constructor. | |
SlidingBuffer (SlidingBuffer &&) noexcept(std::is_nothrow_move_constructible< container_type >::value)=default | |
Default move constructor. | |
SlidingBuffer & | operator= (SlidingBuffer const &)=default |
Default copy assignment operator. | |
SlidingBuffer & | operator= (SlidingBuffer &&) noexcept(std::is_nothrow_move_assignable< container_type >::value)=default |
Default move assignment operator. | |
virtual | ~SlidingBuffer ()=default |
Default Destructor. | |
SlidingBuffer (size_type count) | |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.Only available for sliding buffers based on std::vector. More... | |
auto | pop_back () -> void |
Remove the last element from the buffer. More... | |
auto | pop_front () -> void |
Remove the first element from the buffer. More... | |
auto | push_back (const value_type &in) -> void |
Insert one element at the end of the buffer; if it is full, an element at the front is dropped to make room. More... | |
auto | push_back (value_type &&in) -> void |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
auto | push_front (const value_type &in) -> void |
Insert one element at the front of the buffer; if it is full, an element at the back is dropped to make room. More... | |
auto | push_front (value_type &&in) -> void |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
auto | operator[] (size_type idx) noexcept -> reference |
Access an element in the buffer by index without bounds checking. More... | |
auto | operator[] (size_type idx) const noexcept -> const_reference |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
auto | at (const size_type idx) noexcept(false) -> reference |
Access an element in the buffer by index with bounds checking. More... | |
auto | at (const size_type idx) const noexcept(false) -> const_reference |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
auto | front () noexcept -> reference |
Return the foremost element (the one with index 0). More... | |
auto | front () const noexcept -> const_reference |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
auto | back () noexcept -> reference |
Return the backmost element (the one with the highest valid index). More... | |
auto | back () const noexcept -> const_reference |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
auto | size () const noexcept -> size_type |
Return the number of elements in the container, i.e. More... | |
constexpr auto | capacity () const noexcept -> size_type |
Return the maximum possible number of elements in the container. More... | |
auto | filled () const noexcept -> bool |
Return true if the buffer is completely filled with elements. More... | |
auto | clear () -> void |
Empty the buffer. More... | |
auto | resize (size_type new_capacity, ShrinkBehavior shrink_behavior=ShrinkBehavior::keep_front_elements) -> void |
Resize the container. More... | |
auto | reserve (size_type size, ShrinkBehavior shrink_behavior=ShrinkBehavior::keep_front_elements) -> void |
Resize the container (identical to resize()). More... | |
auto | empty () const noexcept -> bool |
Check if the buffer contains no elements, i.e. More... | |
auto friend | operator<< (std::ostream &s, const SlidingBuffer< value_type, fixed_capacity, container_type > &buffer) -> std::ostream & |
Dump all buffer elements. More... | |
auto | begin () noexcept -> iterator |
Return an iterator to the first element of the container. More... | |
auto | begin () const noexcept -> const_iterator |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
auto | rbegin () noexcept -> reverse_iterator |
Return an iterator to the first element of the reversed container. More... | |
auto | end () noexcept -> iterator |
Return an iterator to the element following the last element of the container. More... | |
auto | end () const noexcept -> const_iterator |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts. | |
auto | rend () noexcept -> reverse_iterator |
Return an iterator to the element following the last element of the reversed container. More... | |
auto | cbegin () const noexcept -> const_iterator |
Return a read-only iterator to the first element of the container. More... | |
auto | crbegin () const noexcept -> const_reverse_iterator |
Return a read-only iterator to the first element of the reversed container. More... | |
auto | cend () const noexcept -> const_iterator |
Return a read-only iterator to the element following the last element of the container. More... | |
auto | crend () const noexcept -> const_reverse_iterator |
Return a read-only iterator to the element following the last element of the reversed container. More... | |
Protected Member Functions | |
auto | change_capacity (size_type new_capacity, ShrinkBehavior shrink_behavior=ShrinkBehavior::keep_front_elements) -> void |
Change the underlying container's capacity. More... | |
Protected Attributes | |
size_type | idx_begin_ { 0u } |
Index of the first SlidingBuffer element in the underlying container (the one retrieved by SlidingBuffer::front()). | |
size_type | idx_end_ { 0u } |
Index pointing to the element in the underlying container that will be written to by the next call to push_back(). | |
bool | full_ { false } |
Indicates if the buffer is completely filled with elements. | |
Container | storage_ { } |
Actual data is stored here, the underlying container. | |
|
default |
Construct an empty sliding buffer.
The capacity of the buffer is given by the fixed_capacity
template parameter. If that template argument is not zero, a std::array based SlidingBuffer with that (unchangeable) capacity is created.
If the template argument is zero, a SlidingBuffer based on std::vector with a capacity of zero elements is generated. Use the SlidingBuffer(size_type) constructor or call the resize() function afterwards to get a SlidingBuffer based on std::vector with nonzero capacity.
|
inline |
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.Only available for sliding buffers based on std::vector.
Constructs a sliding buffer with a specified capacity.
For std::array based sliding buffers the capacity is specified by the fixed_capacity
template parameter.
|
inlinenoexcept |
Access an element in the buffer by index with bounds checking.
Index 0 is the foremost element, size() - 1
the backmost one. Access to elements beyond the last one causes an exception to be thrown.
idx | Index of the element to return |
std::out_of_range | is thrown if idx >= size() . |
References gul14::cat().
|
inlinenoexcept |
Return the backmost element (the one with the highest valid index).
This call does not check if an element has ever been pushed into the buffer, so it might return a default-constructed element. In the case of a SlidingBuffer with zero capacity, calling back() results in undefined behavior.
|
inlinenoexcept |
Return an iterator to the first element of the container.
If the container is empty, the returned iterator will be equal to end().
|
inlineconstexprnoexcept |
Return the maximum possible number of elements in the container.
If the underlying type is std::vector, its size is returned, not its capacity, because only the active elements (i.e. size) participate in the sliding buffer.
|
inlinenoexcept |
Return a read-only iterator to the first element of the container.
If the container is empty, the returned iterator will be equal to cend().
|
inlinenoexcept |
Return a read-only iterator to the element following the last element of the container.
This element acts as a placeholder; attempting to access it results in undefined behavior.
|
inlineprotected |
Change the underlying container's capacity.
Only possible if the underlying container is a std::vector.
shrink_behavior
.new_capacity | New capacity (maximum size) of the sliding buffer. |
shrink_behavior | Specify the ShrinkBehavior. |
|
inline |
Empty the buffer.
(Almost) all iterators will be invalidated. See SlidingBufferIterator.
Its size() will be zero afterwards.
|
inlinenoexcept |
Return a read-only iterator to the first element of the reversed container.
If the container is empty, the returned iterator will be equal to cend().
|
inlinenoexcept |
Return a read-only iterator to the element following the last element of the reversed container.
This element acts as a placeholder; attempting to access it results in undefined behavior.
|
inlinenoexcept |
|
inlinenoexcept |
Return an iterator to the element following the last element of the container.
This element acts as a placeholder; attempting to access it results in undefined behavior.
|
inlinenoexcept |
Return true if the buffer is completely filled with elements.
If the buffer is used in filter contexts this means the filter is fully initialized and working.
If the buffer has zero capacity the value of filled() is false.
|
inlinenoexcept |
Return the foremost element (the one with index 0).
This call does not check if an element has ever been pushed into the buffer, so it might return a default-constructed element. In the case of a SlidingBuffer with zero capacity, calling front() results in undefined behavior.
|
inline |
|
inlinenoexcept |
Access an element in the buffer by index without bounds checking.
Index 0 is the foremost element, size() - 1
the backmost one. Access to elements outside the capacity is not allowed and results in undefined behavior. Access to elements inside the capacity is always allowed; a default-constructed element is returned if idx >= size()
.
|
inline |
Remove the last element from the buffer.
The end() iterator and any iterators to the last element are invalidated.
|
inline |
Remove the first element from the buffer.
The end() iterator and any iterators to the last element are invalidated. All other iterators can still be dereferenced, but point to elements that have been shifted.
|
inline |
Insert one element at the end of the buffer; if it is full, an element at the front is dropped to make room.
At least some iterators can be invalidated. See SlidingBufferIterator.
Afterwards all iterators still point to the same logical element (i.e. element[n]).
|
inline |
Insert one element at the front of the buffer; if it is full, an element at the back is dropped to make room.
At least some iterators can be invalidated. See SlidingBufferIterator.
Afterwards all iterators still point to the same logical element, while the contents of all logical elements is shifted.
|
inlinenoexcept |
Return an iterator to the first element of the reversed container.
If the container is empty, the returned iterator will be equal to end().
|
inlinenoexcept |
Return an iterator to the element following the last element of the reversed container.
This element acts as a placeholder; attempting to access it results in undefined behavior.
|
inline |
|
inline |
Resize the container.
Only possible if the underlying container is a std::vector.
shrink_behavior
.new_capacity | New capacity (maximum size) of the sliding buffer. |
shrink_behavior | Specify the ShrinkBehavior. |
shrink_behavior
(ShrinkBehavior::keep_front_elements) is transparent only if exclusively push_front() was used to add elements. If push_back() was used, resize() without a second argument discards the most recent elements; in these cases, make sure to specify ShrinkBehavior::keep_back_elements.
|
inlinenoexcept |
Return the number of elements in the container, i.e.
std::distance(begin(), end()).
In the startup phase it can be 0 and up to the fixed_capacity
or capacity(), after startup (filled() == true) it will always return fixed_capacity
resp. capacity().