Loading...
Searching...
No Matches
intrusive_list.h
Go to the documentation of this file.
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2016 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#ifndef ETL_INTRUSIVE_LIST_INCLUDED
#define ETL_INTRUSIVE_LIST_INCLUDED
#include "platform.h"
#include "algorithm.h"
#include "error_handler.h"
#include "exception.h"
#include "functional.h"
#include "intrusive_links.h"
#include "iterator.h"
#include "nullptr.h"
#include "static_assert.h"
#include "type_traits.h"
#include <stddef.h>
#include "private/minmax_push.h"
namespace etl
{
//***************************************************************************
//***************************************************************************
class intrusive_list_exception : public exception
{
public:
intrusive_list_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
: exception(reason_, file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class intrusive_list_empty : public intrusive_list_exception
{
public:
intrusive_list_empty(string_type file_name_, numeric_type line_number_)
: intrusive_list_exception(ETL_ERROR_TEXT("intrusive_list:empty", ETL_INTRUSIVE_LIST_FILE_ID"A"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class intrusive_list_iterator_exception : public intrusive_list_exception
{
public:
intrusive_list_iterator_exception(string_type file_name_, numeric_type line_number_)
: intrusive_list_exception(ETL_ERROR_TEXT("intrusive_list:iterator", ETL_INTRUSIVE_LIST_FILE_ID"B"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class intrusive_list_unsorted : public intrusive_list_exception
{
public:
intrusive_list_unsorted(string_type file_name_, numeric_type line_number_)
: intrusive_list_exception(ETL_ERROR_TEXT("intrusive_list:unsorted", ETL_INTRUSIVE_LIST_FILE_ID"C"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
class intrusive_list_value_is_already_linked : public intrusive_list_exception
{
public:
intrusive_list_value_is_already_linked(string_type file_name_, numeric_type line_number_)
: intrusive_list_exception(ETL_ERROR_TEXT("intrusive_list:value is already linked", ETL_INTRUSIVE_LIST_FILE_ID"D"), file_name_, line_number_)
{
}
};
//***************************************************************************
//***************************************************************************
template <typename TLink>
class intrusive_list_base
{
public:
// Node typedef.
typedef TLink link_type;
//*************************************************************************
//*************************************************************************
template <typename TIterator>
void assign(TIterator first, TIterator last)
{
#if ETL_IS_DEBUG_BUILD
intmax_t d = etl::distance(first, last);
ETL_ASSERT(d >= 0, ETL_ERROR(intrusive_list_iterator_exception));
#endif
initialise();
link_type* p_last_link = &terminal_link;
// Add all of the elements.
while (first != last)
{
link_type& link = *first++;
etl::link_splice<link_type>(p_last_link, link);
p_last_link = &link;
++current_size;
}
}
//*************************************************************************
//*************************************************************************
void push_front(link_type& value)
{
ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_list_value_is_already_linked));
insert_link(terminal_link, value);
}
//*************************************************************************
//*************************************************************************
void pop_front()
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(intrusive_list_empty));
disconnect_link(get_head());
}
//*************************************************************************
//*************************************************************************
void push_back(link_type& value)
{
ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_list_value_is_already_linked));
insert_link(terminal_link.link_type::etl_previous, value);
}
//*************************************************************************
//*************************************************************************
void pop_back()
{
ETL_ASSERT_CHECK_PUSH_POP_OR_RETURN(!empty(), ETL_ERROR(intrusive_list_empty));
disconnect_link(get_tail());
}
//*************************************************************************
//*************************************************************************
void clear()
{
// Unlink all of the items.
link_type* p_unlink = terminal_link.etl_next;
while (p_unlink != &terminal_link)
{
link_type* p_next = p_unlink->etl_next;
p_unlink->clear();
p_unlink = p_next;
}
initialise();
}
//*************************************************************************
//*************************************************************************
void reverse()
{
if (is_trivial_list())
{
return;
}
link_type* pnode = terminal_link.etl_next;
while (pnode != &terminal_link)
{
pnode->reverse();
pnode = pnode->etl_previous; // Now we've reversed it, we must go to the
// previous node.
}
// Terminal node.
pnode->reverse();
}
//*************************************************************************
//*************************************************************************
bool empty() const
{
return (terminal_link.link_type::etl_next == &terminal_link);
}
//*************************************************************************
//*************************************************************************
size_t size() const
{
return current_size;
}
//*************************************************************************
//*************************************************************************
bool contains_node(const link_type& search_link) const
{
return is_link_in_list(&search_link);
}
//*************************************************************************
//*************************************************************************
bool contains_node(const link_type* search_link) const
{
return is_link_in_list(search_link);
}
protected:
link_type terminal_link;
size_t current_size;
//*************************************************************************
//*************************************************************************
~intrusive_list_base() {}
//*************************************************************************
//*************************************************************************
bool is_trivial_list() const
{
return (terminal_link.link_type::etl_next == &terminal_link) || (terminal_link.link_type::etl_next->etl_next == &terminal_link);
}
//*************************************************************************
//*************************************************************************
void insert_link(link_type& previous, link_type& new_link)
{
// Connect to the intrusive_list.
etl::link_splice<link_type>(previous, new_link);
++current_size;
}
//*************************************************************************
//*************************************************************************
void insert_link(link_type* previous, link_type& new_link)
{
// Connect to the intrusive_list.
etl::link_splice<link_type>(previous, new_link);
++current_size;
}
//*************************************************************************
//*************************************************************************
void insert_link(link_type& previous, link_type* new_link)
{
// Connect to the intrusive_list.
etl::link_splice<link_type>(previous, new_link);
++current_size;
}
//*************************************************************************
//*************************************************************************
void insert_link(link_type* previous, link_type* new_link)
{
// Connect to the intrusive_list.
etl::link_splice<link_type>(previous, new_link);
++current_size;
}
//*************************************************************************
//*************************************************************************
void disconnect_link(link_type& link)
{
etl::unlink<link_type>(link);
--current_size;
}
//*************************************************************************
//*************************************************************************
void disconnect_link(link_type* link)
{
etl::unlink<link_type>(*link);
--current_size;
}
//*************************************************************************
//*************************************************************************
link_type* get_head()
{
return terminal_link.etl_next;
}
//*************************************************************************
//*************************************************************************
const link_type* get_head() const
{
return terminal_link.etl_next;
}
//*************************************************************************
//*************************************************************************
link_type* get_tail()
{
return terminal_link.etl_previous;
}
//*************************************************************************
//*************************************************************************
const link_type* get_tail() const
{
return terminal_link.etl_previous;
}
//*************************************************************************
//*************************************************************************
void initialise()
{
etl::link(terminal_link, terminal_link);
current_size = 0;
}
//*************************************************************************
//*************************************************************************
bool is_link_in_list(const link_type* search_link) const
{
link_type* p_link = terminal_link.link_type::etl_next;
while (p_link != &terminal_link)
{
if (search_link == p_link)
{
return true;
}
p_link = p_link->link_type::etl_next;
}
return false;
}
//*************************************************************************
//*************************************************************************
link_type* remove_link(link_type* link)
{
link_type* result = ETL_NULLPTR;
if (is_link_in_list(link))
{
link_type* p_next = link->etl_next;
disconnect_link(link);
if (p_next != &terminal_link)
{
result = p_next;
}
}
return result;
}
//*************************************************************************
//*************************************************************************
link_type* remove_link_range(link_type* p_first, link_type* p_last)
{
// Join the ends.
etl::link<link_type>(p_first->etl_previous, p_last);
while (p_first != p_last)
{
link_type* p_next = p_first->etl_next;
p_first->clear();
p_first = p_next;
}
if (p_last == &terminal_link)
{
return ETL_NULLPTR;
}
else
{
return p_last;
}
}
};
//***************************************************************************
//***************************************************************************
template <typename TValue, typename TLink>
class intrusive_list : public etl::intrusive_list_base<TLink>
{
public:
// Node typedef.
typedef typename etl::intrusive_list_base<TLink>::link_type link_type;
typedef intrusive_list<TValue, TLink> list_type;
typedef TValue node_type;
// STL style typedefs.
typedef TValue value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
//*************************************************************************
//*************************************************************************
class iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, value_type>
{
public:
friend class intrusive_list;
friend class const_iterator;
iterator()
: p_value(ETL_NULLPTR)
{
}
iterator(const iterator& other)
: p_value(other.p_value)
{
}
iterator& operator++()
{
// Read the appropriate 'etl_next'.
p_value = p_value->etl_next;
return *this;
}
iterator operator++(int)
{
iterator temp(*this);
// Read the appropriate 'etl_next'.
p_value = p_value->etl_next;
return temp;
}
iterator& operator--()
{
// Read the appropriate 'etl_previous'.
p_value = p_value->etl_previous;
return *this;
}
iterator operator--(int)
{
iterator temp(*this);
// Read the appropriate 'etl_previous'.
p_value = p_value->etl_previous;
return temp;
}
iterator& operator=(const iterator& other)
{
p_value = other.p_value;
return *this;
}
reference operator*() const
{
#include "private/diagnostic_null_dereference_push.h"
return *static_cast<pointer>(p_value);
#include "private/diagnostic_pop.h"
}
pointer operator&() const
{
return static_cast<pointer>(p_value);
}
pointer operator->() const
{
return static_cast<pointer>(p_value);
}
friend bool operator==(const iterator& lhs, const iterator& rhs)
{
return lhs.p_value == rhs.p_value;
}
friend bool operator!=(const iterator& lhs, const iterator& rhs)
{
return !(lhs == rhs);
}
private:
iterator(link_type* value)
: p_value(value)
{
}
link_type* p_value;
};
//*************************************************************************
//*************************************************************************
class const_iterator : public etl::iterator<ETL_OR_STD::bidirectional_iterator_tag, const value_type>
{
public:
friend class intrusive_list;
const_iterator()
: p_value(ETL_NULLPTR)
{
}
const_iterator(const typename intrusive_list::iterator& other)
: p_value(other.p_value)
{
}
const_iterator(const const_iterator& other)
: p_value(other.p_value)
{
}
const_iterator& operator++()
{
// Read the appropriate 'etl_next'.
p_value = p_value->etl_next;
return *this;
}
const_iterator operator++(int)
{
const_iterator temp(*this);
// Read the appropriate 'etl_next'.
p_value = p_value->etl_next;
return temp;
}
const_iterator& operator--()
{
// Read the appropriate 'etl_previous'.
p_value = p_value->etl_previous;
return *this;
}
const_iterator operator--(int)
{
const_iterator temp(*this);
// Read the appropriate 'etl_previous'.
p_value = p_value->etl_previous;
return temp;
}
const_iterator& operator=(const const_iterator& other)
{
p_value = other.p_value;
return *this;
}
const_reference operator*() const
{
return *static_cast<const_pointer>(p_value);
}
const_pointer operator&() const
{
return static_cast<const_pointer>(p_value);
}
const_pointer operator->() const
{
return static_cast<const_pointer>(p_value);
}
friend bool operator==(const const_iterator& lhs, const const_iterator& rhs)
{
return lhs.p_value == rhs.p_value;
}
friend bool operator!=(const const_iterator& lhs, const const_iterator& rhs)
{
return !(lhs == rhs);
}
private:
const_iterator(const link_type* value)
: p_value(value)
{
}
const link_type* p_value;
};
typedef typename etl::iterator_traits<iterator>::difference_type difference_type;
//*************************************************************************
//*************************************************************************
intrusive_list()
{
this->initialise();
}
//*************************************************************************
//*************************************************************************
~intrusive_list()
{
this->clear();
}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
intrusive_list(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral<TIterator>::value, int>::type = 0)
{
this->assign(first, last);
}
#if ETL_USING_CPP11
//*************************************************************************
//*************************************************************************
template <typename... TLinks>
intrusive_list(link_type& first, TLinks&... links)
{
ETL_STATIC_ASSERT((etl::is_base_of_all<link_type, TLinks...>::value), "Mixed link types");
this->current_size = 0;
this->terminal_link.etl_next = &first;
link_type* last = make_linked_list(this->current_size, first, static_cast<link_type&>(links)...);
first.etl_previous = &this->terminal_link;
last->etl_next = &this->terminal_link;
this->terminal_link.etl_previous = last;
}
#endif
//*************************************************************************
//*************************************************************************
iterator begin()
{
return iterator(this->get_head());
}
//*************************************************************************
//*************************************************************************
const_iterator begin() const
{
return const_iterator(this->get_head());
}
//*************************************************************************
//*************************************************************************
const_iterator cbegin() const
{
return const_iterator(this->get_head());
}
//*************************************************************************
//*************************************************************************
iterator end()
{
return iterator(&this->terminal_link);
}
//*************************************************************************
//*************************************************************************
const_iterator end() const
{
return const_iterator(&this->terminal_link);
}
//*************************************************************************
//*************************************************************************
const_iterator cend() const
{
return const_iterator(&this->terminal_link);
}
//*************************************************************************
//*************************************************************************
reference front()
{
ETL_ASSERT_CHECK_EXTRA(!this->empty(), ETL_ERROR(intrusive_list_empty));
return *static_cast<pointer>(this->get_head());
}
//*************************************************************************
//*************************************************************************
const_reference front() const
{
ETL_ASSERT_CHECK_EXTRA(!this->empty(), ETL_ERROR(intrusive_list_empty));
return *static_cast<const_pointer>(this->get_head());
}
//*************************************************************************
//*************************************************************************
reference back()
{
ETL_ASSERT_CHECK_EXTRA(!this->empty(), ETL_ERROR(intrusive_list_empty));
return *static_cast<pointer>(this->get_tail());
}
//*************************************************************************
//*************************************************************************
const_reference back() const
{
ETL_ASSERT_CHECK_EXTRA(!this->empty(), ETL_ERROR(intrusive_list_empty));
return *static_cast<const_pointer>(this->get_tail());
}
//*************************************************************************
//*************************************************************************
iterator insert(const_iterator position, value_type& value)
{
this->insert_link(position.p_value->link_type::etl_previous, value);
return iterator(&value);
}
//*************************************************************************
//*************************************************************************
template <typename TIterator>
void insert(const_iterator position, TIterator first, TIterator last)
{
while (first != last)
{
// Set up the next free link.
this->insert_link(*position.p_value->link_type::etl_previous, *first);
++first;
}
}
//*************************************************************************
//*************************************************************************
iterator erase(iterator position)
{
iterator next(position);
++next;
this->disconnect_link(*position.p_value);
return next;
}
//*************************************************************************
//*************************************************************************
iterator erase(const_iterator position)
{
iterator next(position);
++next;
this->disconnect_link(*position.p_value);
return next;
}
//*************************************************************************
//*************************************************************************
iterator erase(const_iterator first, const_iterator last)
{
const link_type* cp_first = first.p_value;
const link_type* cp_last = last.p_value;
link_type* p_first = const_cast<link_type*>(cp_first);
link_type* p_last = const_cast<link_type*>(cp_last);
this->current_size -= static_cast<size_t>(etl::distance(first, last));
p_last = this->remove_link_range(p_first, p_last);
if (p_last == ETL_NULLPTR)
{
return end();
}
else
{
return iterator(static_cast<pointer>(p_last));
}
}
//*************************************************************************
//*************************************************************************
node_type* erase(const node_type& node)
{
return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(&node)));
}
//*************************************************************************
//*************************************************************************
node_type* erase(const node_type* p_node)
{
return static_cast<node_type*>(this->remove_link(const_cast<node_type*>(p_node)));
}
//*************************************************************************
//*************************************************************************
template <typename TIsEqual>
void unique(TIsEqual isEqual)
{
if (this->empty())
{
return;
}
iterator i_item = begin();
++i_item;
iterator i_previous = begin();
while (i_item != end())
{
if (isEqual(*i_previous, *i_item))
{
i_item = erase(i_item);
}
else
{
i_previous = i_item;
++i_item;
}
}
}
//*************************************************************************
//*************************************************************************
void sort()
{
sort(etl::less<value_type>());
}
//*************************************************************************
//*************************************************************************
template <typename TCompare>
void sort(TCompare compare)
{
iterator i_left;
iterator i_right;
iterator i_node;
iterator i_head;
iterator i_tail;
int list_size = 1;
int number_of_merges;
int left_size;
int right_size;
if (this->is_trivial_list())
{
return;
}
while (true)
{
i_left = begin();
i_head = end();
i_tail = end();
number_of_merges = 0; // Count the number of merges we do in this pass.
while (i_left != end())
{
++number_of_merges; // There exists a merge to be done.
i_right = i_left;
left_size = 0;
// Step 'list_size' places along from left
for (int i = 0; i < list_size; ++i)
{
++left_size;
++i_right;
if (i_right == end())
{
break;
}
}
// If right hasn't fallen off end, we have two lists to merge.
right_size = list_size;
// Now we have two lists. Merge them.
while (left_size > 0 || (right_size > 0 && i_right != end()))
{
// Decide whether the next node of merge comes from left or right.
if (left_size == 0)
{
// Left is empty. The node must come from right.
i_node = i_right++;
--right_size;
}
else if (right_size == 0 || i_right == end())
{
// Right is empty. The node must come from left.
i_node = i_left++;
--left_size;
}
else if (!compare(*i_right, *i_left))
{
// First node of left is lower or same. The node must come from
// left.
i_node = i_left++;
--left_size;
}
else
{
// First node of right is lower. The node must come from right.
i_node = i_right;
++i_right;
--right_size;
}
// Add the next node to the merged head.
if (i_head == end())
{
etl::link<link_type>(i_head.p_value, i_node.p_value);
i_head = i_node;
i_tail = i_node;
}
else
{
etl::link<link_type>(i_tail.p_value, i_node.p_value);
i_tail = i_node;
}
etl::link<link_type>(i_tail.p_value, this->terminal_link);
}
// Now left has stepped `list_size' places along, and right has too.
i_left = i_right;
}
// If we have done only one merge, we're finished.
if (number_of_merges <= 1) // Allow for number_of_merges == 0, the empty head case
{
return;
}
// Otherwise repeat, merging lists twice the size
list_size *= 2;
}
}
//*************************************************************************
// Removes the values specified.
//*************************************************************************
void remove(const_reference value)
{
iterator i_item = begin();
while (i_item != end())
{
if (*i_item == value)
{
i_item = erase(i_item);
}
else
{
++i_item;
}
}
}
//*************************************************************************
//*************************************************************************
template <typename TPredicate>
void remove_if(TPredicate predicate)
{
iterator i_item = begin();
while (i_item != end())
{
if (predicate(*i_item))
{
i_item = erase(i_item);
}
else
{
++i_item;
}
}
}
//*************************************************************************
//*************************************************************************
void splice(iterator position, list_type& other)
{
// No point splicing to ourself!
if (&other != this)
{
if (!other.empty())
{
link_type& first = *other.get_head();
link_type& last = *other.get_tail();
if (&other != this)
{
this->current_size += other.size();
}
link_type& after = *position.p_value;
link_type& before = *after.etl_previous;
etl::link<link_type>(before, first);
etl::link<link_type>(last, after);
other.initialise();
}
}
}
//*************************************************************************
//*************************************************************************
void splice(iterator position, list_type& other, iterator isource)
{
link_type& before = *position.p_value->link_type::etl_previous;
etl::unlink<link_type>(*isource.p_value);
etl::link_splice<link_type>(before, *isource.p_value);
if (&other != this)
{
++this->current_size;
--other.current_size;
}
}
//*************************************************************************
//*************************************************************************
void splice(iterator position, list_type& other, iterator begin_, iterator end_)
{
if (!other.empty())
{
if (&other != this)
{
size_t n = static_cast<size_t>(etl::distance(begin_, end_));
this->current_size += n;
other.current_size -= n;
}
link_type& first = *begin_.p_value;
link_type& last = *end_.p_value->link_type::etl_previous;
// Unlink from the source list.
etl::unlink(first, last);
// Fix our links.
link_type& before = *position.p_value->link_type::etl_previous;
etl::link_splice<link_type>(before, first, last);
}
}
//*************************************************************************
//*************************************************************************
void merge(list_type& other)
{
merge(other, etl::less<value_type>());
}
//*************************************************************************
//*************************************************************************
template <typename TCompare>
void merge(list_type& other, TCompare compare)
{
if ((this != &other) && !other.empty())
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(intrusive_list_unsorted));
ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(intrusive_list_unsorted));
#endif
link_type* other_begin = other.get_head();
link_type* other_end = &other.terminal_link;
link_type* this_begin = this->get_head();
link_type* this_end = &this->terminal_link;
while ((this_begin != this_end) && (other_begin != other_end))
{
// Find the place to insert.
while ((this_begin != this_end) && !(compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(this_begin))))
{
this_begin = this_begin->etl_next;
}
// Insert.
if (this_begin != this_end)
{
while ((other_begin != other_end) && (compare(*static_cast<pointer>(other_begin), *static_cast<pointer>(this_begin))))
{
link_type* value = other_begin;
other_begin = other_begin->etl_next;
etl::link_splice<link_type>(*this_begin->etl_previous, *value);
}
}
}
// Any left over?
if ((this_begin == this_end) && (other_begin != other_end))
{
etl::link_splice<link_type>(*this->get_tail(), *other_begin, *other_end->etl_previous);
}
this->current_size += other.size();
other.initialise();
}
}
//*************************************************************************
//*************************************************************************
bool contains(const_reference value) const
{
const_iterator i_item = begin();
while (i_item != end())
{
if (*i_item == value)
{
return true;
}
++i_item;
}
return false;
}
private:
#if ETL_USING_CPP17
//***************************************************************************
//***************************************************************************
template <typename... TLinks>
link_type* make_linked_list(size_t& count, link_type& first, TLinks&... links)
{
TLink* current = &first;
++count;
((current->etl_next = &links, static_cast<TLink&>(links).etl_previous = current, current = &links, ++count), ...);
return current;
}
#elif ETL_USING_CPP11
//***************************************************************************
//***************************************************************************
link_type* make_linked_list(size_t& count, link_type& first)
{
++count;
return &first;
}
//***************************************************************************
//***************************************************************************
template <typename... TLinks>
link_type* make_linked_list(size_t& count, link_type& first, link_type& next, TLinks&... links)
{
++count;
first.etl_next = &next;
next.etl_previous = &first;
return make_linked_list(count, next, static_cast<link_type&>(links)...);
}
#endif
// Disabled.
intrusive_list(const intrusive_list& other);
intrusive_list& operator=(const intrusive_list& rhs);
};
} // namespace etl
#include "private/minmax_pop.h"
#endif
algorithm.h
etl::link_type
etl::intrusive_list::const_iterator
const_iterator
Definition intrusive_list.h:586
etl::intrusive_list::iterator
iterator.
Definition intrusive_list.h:493
etl::intrusive_list_base
Definition intrusive_list.h:127
etl::intrusive_list_base::disconnect_link
void disconnect_link(link_type *link)
Remove a link.
Definition intrusive_list.h:347
etl::intrusive_list_base::size
size_t size() const
Returns the number of elements.
Definition intrusive_list.h:252
etl::intrusive_list_base::get_tail
link_type * get_tail()
Get the tail link.
Definition intrusive_list.h:372
etl::intrusive_list_base::insert_link
void insert_link(link_type &previous, link_type &new_link)
Insert a link.
Definition intrusive_list.h:298
etl::intrusive_list_base::~intrusive_list_base
~intrusive_list_base()
Destructor.
Definition intrusive_list.h:285
etl::intrusive_list_base::assign
void assign(TIterator first, TIterator last)
Definition intrusive_list.h:139
etl::intrusive_list_base::contains_node
bool contains_node(const link_type *search_link) const
Definition intrusive_list.h:270
etl::link_type::current_size
size_t current_size
Definition intrusive_list.h:280
etl::intrusive_list_base::is_link_in_list
bool is_link_in_list(const link_type *search_link) const
Tests if the link is in this list.
Definition intrusive_list.h:397
etl::intrusive_list_base::disconnect_link
void disconnect_link(link_type &link)
Remove a link.
Definition intrusive_list.h:338
etl::intrusive_list_base::insert_link
void insert_link(link_type &previous, link_type *new_link)
Insert a link.
Definition intrusive_list.h:318
etl::intrusive_list_base::pop_back
void pop_back()
Removes a value from the back of the intrusive_list.
Definition intrusive_list.h:193
etl::intrusive_list_base::get_head
link_type * get_head()
Get the head link.
Definition intrusive_list.h:356
etl::intrusive_list_base::empty
bool empty() const
Returns true if the list has no elements.
Definition intrusive_list.h:244
etl::intrusive_list_base::remove_link_range
link_type * remove_link_range(link_type *p_first, link_type *p_last)
Removes a range of links.
Definition intrusive_list.h:441
etl::intrusive_list_base::initialise
void initialise()
Initialise the intrusive_list.
Definition intrusive_list.h:388
etl::intrusive_list_base::reverse
void reverse()
Reverses the list.
Definition intrusive_list.h:221
etl::intrusive_list_base::insert_link
void insert_link(link_type *previous, link_type *new_link)
Insert a link.
Definition intrusive_list.h:328
etl::intrusive_list_base::get_head
const link_type * get_head() const
Get the head link.
Definition intrusive_list.h:364
etl::link_type::terminal_link
link_type terminal_link
Definition intrusive_list.h:278
etl::intrusive_list_base::insert_link
void insert_link(link_type *previous, link_type &new_link)
Insert a link.
Definition intrusive_list.h:308
etl::intrusive_list_base::clear
void clear()
Clears the intrusive_list.
Definition intrusive_list.h:203
etl::intrusive_list_base::push_front
void push_front(link_type &value)
Pushes a value to the front of the intrusive_list.
Definition intrusive_list.h:163
etl::intrusive_list_base::push_back
void push_back(link_type &value)
Pushes a value to the back of the intrusive_list.
Definition intrusive_list.h:183
etl::intrusive_list_base::pop_front
void pop_front()
Removes a value from the front of the intrusive_list.
Definition intrusive_list.h:173
etl::intrusive_list_base::contains_node
bool contains_node(const link_type &search_link) const
Definition intrusive_list.h:261
etl::intrusive_list_base::get_tail
const link_type * get_tail() const
Get the tail link.
Definition intrusive_list.h:380
etl::intrusive_list_base::is_trivial_list
bool is_trivial_list() const
Is the intrusive_list a trivial length?
Definition intrusive_list.h:290
etl::intrusive_list_base::remove_link
link_type * remove_link(link_type *link)
Definition intrusive_list.h:419
etl::intrusive_list_empty
Definition intrusive_list.h:70
etl::intrusive_list_iterator_exception
Definition intrusive_list.h:84
etl::intrusive_list_unsorted
Definition intrusive_list.h:98
etl::intrusive_list_value_is_already_linked
Definition intrusive_list.h:112
etl::intrusive_list::~intrusive_list
~intrusive_list()
Destructor.
Definition intrusive_list.h:690
etl::intrusive_list::end
const_iterator end() const
Gets the end of the intrusive_list.
Definition intrusive_list.h:757
etl::intrusive_list::back
reference back()
Definition intrusive_list.h:797
etl::intrusive_list::begin
iterator begin()
Gets the beginning of the intrusive_list.
Definition intrusive_list.h:725
etl::intrusive_list::erase
node_type * erase(const node_type &node)
Erases the specified node.
Definition intrusive_list.h:893
etl::intrusive_list::unique
void unique(TIsEqual isEqual)
Definition intrusive_list.h:911
etl::intrusive_list::begin
const_iterator begin() const
Gets the beginning of the intrusive_list.
Definition intrusive_list.h:733
etl::intrusive_list::splice
void splice(iterator position, list_type &other)
Splice another list into this one.
Definition intrusive_list.h:1122
etl::intrusive_list::erase
iterator erase(const_iterator position)
Erases the value at the specified position.
Definition intrusive_list.h:854
etl::intrusive_list::splice
void splice(iterator position, list_type &other, iterator begin_, iterator end_)
Splice a range of elements from another list into this one.
Definition intrusive_list.h:1168
etl::intrusive_list::front
reference front()
Definition intrusive_list.h:775
etl::intrusive_list::insert
void insert(const_iterator position, TIterator first, TIterator last)
Definition intrusive_list.h:828
etl::intrusive_list::merge
void merge(list_type &other, TCompare compare)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_list.h:1204
etl::intrusive_list::contains
bool contains(const_reference value) const
Definition intrusive_list.h:1255
etl::intrusive_list::sort
void sort(TCompare compare)
Definition intrusive_list.h:970
etl::intrusive_list::splice
void splice(iterator position, list_type &other, iterator isource)
Splice an element from another list into this one.
Definition intrusive_list.h:1151
etl::intrusive_list::intrusive_list
intrusive_list()
Constructor.
Definition intrusive_list.h:682
etl::intrusive_list::erase
iterator erase(const_iterator first, const_iterator last)
Definition intrusive_list.h:868
etl::intrusive_list::cend
const_iterator cend() const
Gets the end of the intrusive_list.
Definition intrusive_list.h:765
etl::intrusive_list::erase
iterator erase(iterator position)
Erases the value at the specified position.
Definition intrusive_list.h:841
etl::intrusive_list::cbegin
const_iterator cbegin() const
Gets the beginning of the intrusive_list.
Definition intrusive_list.h:741
etl::intrusive_list::remove_if
void remove_if(TPredicate predicate)
Removes according to a predicate.
Definition intrusive_list.h:1102
etl::intrusive_list::sort
void sort()
Sort using in-place merge sort algorithm.
Definition intrusive_list.h:939
etl::intrusive_list::insert
iterator insert(const_iterator position, value_type &value)
Inserts a value to the intrusive_list before the specified position.
Definition intrusive_list.h:817
etl::intrusive_list::front
const_reference front() const
Definition intrusive_list.h:786
etl::intrusive_list::end
iterator end()
Gets the end of the intrusive_list.
Definition intrusive_list.h:749
etl::intrusive_list::erase
node_type * erase(const node_type *p_node)
Erases the specified node.
Definition intrusive_list.h:901
etl::intrusive_list::intrusive_list
intrusive_list(TIterator first, TIterator last, typename etl::enable_if<!etl::is_integral< TIterator >::value, int >::type=0)
Constructor from range.
Definition intrusive_list.h:699
etl::intrusive_list::back
const_reference back() const
Definition intrusive_list.h:808
etl::intrusive_list::merge
void merge(list_type &other)
Merge another list into this one. Both lists should be sorted.
Definition intrusive_list.h:1195
diagnostic_null_dereference_push.h
diagnostic_pop.h
error_handler.h
exception.h
functional.h
etl::is_sorted
ETL_NODISCARD ETL_CONSTEXPR14 bool is_sorted(TIterator begin, TIterator end)
Definition algorithm.h:1669
etl::remove
ETL_CONSTEXPR14 TIterator remove(TIterator first, TIterator last, const T &value)
Definition algorithm.h:2381
ETL_ASSERT
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
etl::exception::exception
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
intrusive_links.h
iterator.h
minmax_pop.h
minmax_push.h
etl
Definition absolute.h:40
etl::operator*
ETL_CONSTEXPR14 enable_if<!etl::is_specialization< TRep2, etl::chrono::duration >::value, etl::chrono::duration< typenameetl::common_type< TRep1, TRep2 >::type, TPeriod1 > >::type operator*(const etl::chrono::duration< TRep1, TPeriod1 > &lhs, const TRep2 &rhs) ETL_NOEXCEPT
Operator *.
Definition duration.h:541
nullptr.h
platform.h
etl::compare
Definition compare.h:51
etl::iterator
iterator
Definition iterator.h:482
etl::less
Definition functional.h:201
etl::type
operator==
ETL_CONSTEXPR14 bool operator==(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Equality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:903
operator!=
ETL_CONSTEXPR14 bool operator!=(const etl::to_arithmetic_result< T > &lhs, const etl::to_arithmetic_result< T > &rhs)
Inequality test for etl::to_arithmetic_result.
Definition to_arithmetic.h:937
type_traits.h