From 3510fd61a96fe6dc3f144c90db034f677cfe53d4 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 26 Jun 2023 08:07:40 +0100 Subject: [PATCH] Updated intrusive links Refactored intrusive_forward_list so that links report status consistantly --- .gitignore | 1 + include/etl/forward_list.h | 26 +- include/etl/intrusive_forward_list.h | 146 +++++++---- include/etl/intrusive_links.h | 97 ++++++- include/etl/intrusive_list.h | 21 +- include/etl/intrusive_queue.h | 61 +++-- include/etl/intrusive_stack.h | 45 ++-- include/etl/list.h | 36 +-- include/etl/map.h | 10 +- include/etl/multimap.h | 6 +- include/etl/multiset.h | 6 +- include/etl/set.h | 6 +- include/etl/unordered_map.h | 61 +++-- include/etl/unordered_multimap.h | 57 +++-- include/etl/unordered_multiset.h | 57 +++-- include/etl/unordered_set.h | 117 ++++----- support/Release notes.txt | 1 + test/test_intrusive_forward_list.cpp | 87 ++++++- test/test_intrusive_links.cpp | 12 +- test/test_intrusive_list.cpp | 163 +++++++++++- test/test_intrusive_queue.cpp | 133 ++++++---- test/test_intrusive_stack.cpp | 24 +- test/vs2022/etl.sln | 6 + test/vs2022/etl.vcxproj | 370 +++++++++++++++++++++++++++ 24 files changed, 1213 insertions(+), 336 deletions(-) diff --git a/.gitignore b/.gitignore index 2fb15355..1cfe04f8 100644 --- a/.gitignore +++ b/.gitignore @@ -380,3 +380,4 @@ test/vs2022/Debug MSVC C++17 test/vs2022/Debug MSVC C++17 - No STL test/vs2022/Release MSVC C++20 - No STL - Optimised -O2 test/vs2022/Release MSVC C++20 - Optimised O2 +test/vs2022/Debug MSVC C++ 20 - No Tests diff --git a/include/etl/forward_list.h b/include/etl/forward_list.h index 98da9b7e..c149ada3 100644 --- a/include/etl/forward_list.h +++ b/include/etl/forward_list.h @@ -727,7 +727,7 @@ namespace etl #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); #endif - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(etl::forward(args)...); ETL_INCREMENT_DEBUG_COUNT insert_node_after(start_node, *p_data_node); @@ -743,7 +743,7 @@ namespace etl #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); #endif - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1); ETL_INCREMENT_DEBUG_COUNT insert_node_after(start_node, *p_data_node); @@ -759,7 +759,7 @@ namespace etl #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); #endif - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2); ETL_INCREMENT_DEBUG_COUNT insert_node_after(start_node, *p_data_node); @@ -775,7 +775,7 @@ namespace etl #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); #endif - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3); ETL_INCREMENT_DEBUG_COUNT insert_node_after(start_node, *p_data_node); @@ -791,7 +791,7 @@ namespace etl #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); #endif - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3, value4); ETL_INCREMENT_DEBUG_COUNT insert_node_after(start_node, *p_data_node); @@ -888,7 +888,7 @@ namespace etl { ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(etl::forward(args)...); ETL_INCREMENT_DEBUG_COUNT insert_node_after(*to_iterator(position).p_node, *p_data_node); @@ -904,7 +904,7 @@ namespace etl { ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1); ETL_INCREMENT_DEBUG_COUNT insert_node_after(*position.p_node, *p_data_node); @@ -920,7 +920,7 @@ namespace etl { ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2); ETL_INCREMENT_DEBUG_COUNT insert_node_after(*position.p_node, *p_data_node); @@ -936,7 +936,7 @@ namespace etl { ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3); ETL_INCREMENT_DEBUG_COUNT insert_node_after(*position.p_node, *p_data_node); @@ -952,7 +952,7 @@ namespace etl { ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3, value4); ETL_INCREMENT_DEBUG_COUNT insert_node_after(*position.p_node, *p_data_node); @@ -1457,7 +1457,7 @@ namespace etl //************************************************************************* data_node_t& allocate_data_node(const_reference value) { - data_node_t* p_node = create_data_node(); + data_node_t* p_node = allocate_data_node(); ::new (&(p_node->value)) T(value); ETL_INCREMENT_DEBUG_COUNT @@ -1470,7 +1470,7 @@ namespace etl //************************************************************************* data_node_t& allocate_data_node(rvalue_reference value) { - data_node_t* p_node = create_data_node(); + data_node_t* p_node = allocate_data_node(); ::new (&(p_node->value)) T(etl::move(value)); ETL_INCREMENT_DEBUG_COUNT @@ -1582,7 +1582,7 @@ namespace etl //************************************************************************* /// Create a node. //************************************************************************* - data_node_t* create_data_node() + data_node_t* allocate_data_node() { data_node_t* (etl::ipool::*func)() = &etl::ipool::allocate; return (p_node_pool->*func)(); diff --git a/include/etl/intrusive_forward_list.h b/include/etl/intrusive_forward_list.h index 5c7f7490..2bf03bd8 100644 --- a/include/etl/intrusive_forward_list.h +++ b/include/etl/intrusive_forward_list.h @@ -117,6 +117,20 @@ namespace etl } }; + //*************************************************************************** + /// intrusive_stack_value_is_already_linked exception. + ///\ingroup intrusive_stack + //*************************************************************************** + class intrusive_forward_list_value_is_already_linked : public intrusive_forward_list_exception + { + public: + + intrusive_forward_list_value_is_already_linked(string_type file_name_, numeric_type line_number_) + : intrusive_forward_list_exception(ETL_ERROR_TEXT("intrusive_forward_list:value is already linked", ETL_INTRUSIVE_FORWARD_LIST_FILE_ID"E"), file_name_, line_number_) + { + } + }; + //*************************************************************************** /// Base for intrusive forward list. ///\ingroup intrusive_forward_list @@ -134,6 +148,16 @@ namespace etl //************************************************************************* void clear() { + // Unlink all of the items. + link_type* p_unlink = start.etl_next; + + while (p_unlink != &terminator) + { + link_type* p_next = p_unlink->etl_next; + p_unlink->clear(); + p_unlink = p_next; + } + initialise(); } @@ -146,19 +170,27 @@ namespace etl { #if ETL_IS_DEBUG_BUILD intmax_t d = etl::distance(first, last); - ETL_ASSERT(d >= 0, ETL_ERROR(intrusive_forward_list_iterator_exception)); + ETL_ASSERT_OR_RETURN(d >= 0, ETL_ERROR(intrusive_forward_list_iterator_exception)); #endif - initialise(); + clear(); - link_type* p_last_link = &start_link; + link_type* p_last = &start; + + int count = 0; // Add all of the elements. while (first != last) { - link_type& link = *first++; - etl::link_splice(p_last_link, link); - p_last_link = &link; + ++count; + + link_type& value = *first++; + + ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked)); + + value.etl_next = p_last->etl_next; + p_last->etl_next = &value; + p_last = &value; ++current_size; } } @@ -168,7 +200,9 @@ namespace etl //************************************************************************* void push_front(link_type& value) { - insert_link_after(start_link, value); + ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked)); + + insert_link_after(start, value); } //************************************************************************* @@ -177,9 +211,9 @@ namespace etl void pop_front() { #if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(intrusive_forward_list_empty)); + ETL_ASSERT_OR_RETURN(!empty(), ETL_ERROR(intrusive_forward_list_empty)); #endif - remove_link_after(start_link); + remove_link_after(start); } //************************************************************************* @@ -192,19 +226,19 @@ namespace etl return; } - link_type* first = ETL_NULLPTR; // To keep first link - link_type* second = start_link.etl_next; // To keep second link - link_type* track = start_link.etl_next; // Track the list - - while (track != NULL) + link_type* previous = &terminator; // Point to the terminator of the linked list. + link_type* current = start.etl_next; // Point to the first item in the linked list (could be the terminator). + link_type* next = start.etl_next; // Point to the first item in the linked list (could be the terminator). + + while (next != &terminator) { - track = track->etl_next; // Track point to next link; - second->etl_next = first; // Second link point to first - first = second; // Move first link to next - second = track; // Move second link to next + next = next->etl_next; // Point to next link. + current->etl_next = previous; // Reverse the current link. + previous = current; // Previous points to current. + current = next; // Current points to next. } - etl::link(start_link, first); + etl::link(start, previous); } //************************************************************************* @@ -212,7 +246,7 @@ namespace etl //************************************************************************* bool empty() const { - return start_link.etl_next == ETL_NULLPTR; + return (current_size == 0); } //************************************************************************* @@ -225,15 +259,25 @@ namespace etl protected: - link_type start_link; ///< The link that acts as the intrusive_forward_list start. + link_type start; ///< The link pointer that acts as the intrusive_forward_list start. + static link_type terminator; ///< The link that acts as the intrusive_forward_list terminator. size_t current_size; ///< Counts the number of elements in the list. + //************************************************************************* + /// Constructor + //************************************************************************* + intrusive_forward_list_base() + { + initialise(); + } + //************************************************************************* /// Destructor //************************************************************************* ~intrusive_forward_list_base() { + clear(); } //************************************************************************* @@ -241,7 +285,7 @@ namespace etl //************************************************************************* bool is_trivial_list() const { - return (start_link.link_type::etl_next == ETL_NULLPTR) || (start_link.link_type::etl_next->etl_next == ETL_NULLPTR); + return (size() <= 1U); } //************************************************************************* @@ -263,7 +307,8 @@ namespace etl if (p_next != ETL_NULLPTR) { - etl::unlink_after(link); + link_type* p_unlinked = etl::unlink_after(link); + p_unlinked->clear(); --current_size; } } @@ -273,7 +318,7 @@ namespace etl //************************************************************************* link_type* get_head() { - return start_link.etl_next; + return start.etl_next; } //************************************************************************* @@ -281,7 +326,7 @@ namespace etl //************************************************************************* const link_type* get_head() const { - return start_link.etl_next; + return start.etl_next; } //************************************************************************* @@ -289,17 +334,20 @@ namespace etl //************************************************************************* void initialise() { - start_link.etl_next = ETL_NULLPTR; + start.etl_next = &terminator; current_size = 0; } }; + template + TLink etl::intrusive_forward_list_base::terminator; + //*************************************************************************** /// An intrusive forward list. ///\ingroup intrusive_forward_list ///\note TLink must be a base of TValue. //*************************************************************************** - template > + template class intrusive_forward_list : public etl::intrusive_forward_list_base { public: @@ -480,7 +528,6 @@ namespace etl //************************************************************************* intrusive_forward_list() { - this->initialise(); } //************************************************************************* @@ -488,7 +535,6 @@ namespace etl //************************************************************************* ~intrusive_forward_list() { - this->clear(); } //************************************************************************* @@ -521,7 +567,7 @@ namespace etl //************************************************************************* iterator before_begin() { - return iterator(&this->start_link); + return iterator(&this->start); } //************************************************************************* @@ -529,7 +575,7 @@ namespace etl //************************************************************************* const_iterator before_begin() const { - return const_iterator(&this->start_link); + return const_iterator(&this->start); } //************************************************************************* @@ -545,7 +591,7 @@ namespace etl //************************************************************************* iterator end() { - return iterator(); + return iterator(&this->terminator); } //************************************************************************* @@ -553,7 +599,7 @@ namespace etl //************************************************************************* const_iterator end() const { - return const_iterator(); + return const_iterator(&this->terminator); } //************************************************************************* @@ -561,7 +607,7 @@ namespace etl //************************************************************************* const_iterator cend() const { - return const_iterator(); + return const_iterator(&this->terminator); } //************************************************************************* @@ -585,6 +631,8 @@ namespace etl //************************************************************************* iterator insert_after(iterator position, value_type& value) { + ETL_ASSERT_OR_RETURN_VALUE(!value.link_type::is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked), iterator(&value)); + this->insert_link_after(*position.p_value, value); return iterator(&value); } @@ -598,6 +646,8 @@ namespace etl while (first != last) { // Set up the next free link. + ETL_ASSERT_OR_RETURN(!(*first).link_type::is_linked(), ETL_ERROR(intrusive_forward_list_value_is_already_linked)); + this->insert_link_after(*position.p_value, *first); ++first; ++position; @@ -633,13 +683,23 @@ namespace etl this->current_size -= etl::distance(first, last) - 1; link_type* p_first = first.p_value; - link_type* p_last = last.p_value; - link_type* p_next = p_first->etl_next; - + link_type* p_last = last.p_value; + link_type* p_after = p_first->etl_next; + // Join the ends. etl::link(p_first, p_last); - if (p_next == ETL_NULLPTR) + // Unlink the erased range. + link_type* p_unlink = p_after; + + while (p_unlink != p_last) + { + link_type* p_next = p_unlink->etl_next; + p_unlink->clear(); + p_unlink = p_next; + } + + if (p_after == &this->terminator) { return end(); } @@ -813,7 +873,7 @@ namespace etl i_tail = i_link; } - i_tail.p_value->etl_next = ETL_NULLPTR; + i_tail.p_value->etl_next = &this->terminator; } // Now left has stepped `list_size' places along, and right has too. @@ -899,7 +959,7 @@ namespace etl etl::link(before, first); link_type* last = &before; - while (last->etl_next != ETL_NULLPTR) + while (last->etl_next != &other.terminator) { last = last->etl_next; } @@ -983,11 +1043,11 @@ namespace etl #endif link_type* other_begin = other.get_head(); - link_type* other_terminal = ETL_NULLPTR; + link_type* other_terminal = &other.terminator; - link_type* before = &this->start_link; + link_type* before = &this->start; link_type* before_next = get_next(before); - link_type* terminal = ETL_NULLPTR; + link_type* terminal = &this->terminator;; while ((before->etl_next != terminal) && (other_begin != other_terminal)) { diff --git a/include/etl/intrusive_links.h b/include/etl/intrusive_links.h index cf17ff1e..577f5010 100644 --- a/include/etl/intrusive_links.h +++ b/include/etl/intrusive_links.h @@ -97,6 +97,12 @@ namespace etl { } + //*********************************** + forward_link(forward_link* p_next) + : etl_next(p_next) + { + } + //*********************************** forward_link(const forward_link& other) : etl_next(other.etl_next) @@ -298,14 +304,18 @@ namespace etl //*************************************************************************** // Reference template - typename etl::enable_if::value, void>::type + typename etl::enable_if::value, TLink*>::type unlink_after(TLink& node) { if (node.etl_next != ETL_NULLPTR) { TLink* unlinked_node = node.etl_next; node.etl_next = unlinked_node->etl_next; + unlinked_node->clear(); + return unlinked_node; } + + return node.etl_next; } //*********************************** @@ -319,13 +329,53 @@ namespace etl if (&before != &last) { before.etl_next = last.etl_next; + last.clear(); } return first; } + // Reference + template + typename etl::enable_if::value, bool>::type + is_linked(TLink& node) + { + return node.is_linked(); + } + + // Pointer + template + typename etl::enable_if::value, bool>::type + is_linked(TLink* node) + { + return node->is_linked(); + } + //*************************************************************************** - // link_clear_range + // link_clear + //*************************************************************************** + // Reference + template + typename etl::enable_if::value, void>::type + link_clear(TLink& start) + { + start.etl_next = ETL_NULLPTR; + } + + //*********************************** + // Pointer + template + typename etl::enable_if::value, void>::type + link_clear(TLink* start) + { + if (start != ETL_NULLPTR) + { + etl::link_clear(*start); + } + } + + //*************************************************************************** + // link_clear //*************************************************************************** // Reference template @@ -348,7 +398,10 @@ namespace etl typename etl::enable_if::value, void>::type link_clear_range(TLink* start) { - etl::link_clear_range(*start); + if (start != ETL_NULLPTR) + { + etl::link_clear_range(*start); + } } //*************************************************************************** @@ -369,6 +422,13 @@ namespace etl { } + //*********************************** + bidirectional_link(bidirectional_link* p_previous, bidirectional_link* p_next) + : etl_previous(p_previous) + , etl_next(p_next) + { + } + //*********************************** bidirectional_link(const bidirectional_link& other) : etl_previous(other.etl_previous) @@ -716,6 +776,7 @@ namespace etl if (first.etl_previous != ETL_NULLPTR) { first.etl_previous->etl_next = last.etl_next; + last.clear(); } first.etl_previous = ETL_NULLPTR; @@ -725,6 +786,22 @@ namespace etl return first; } + // Reference + template + typename etl::enable_if >::value, bool>::type + is_linked(TLink& node) + { + return node.is_linked(); + } + + // Pointer + template + typename etl::enable_if >::value, bool>::type + is_linked(TLink* node) + { + return node->is_linked(); + } + //*************************************************************************** // link_clear_range //*************************************************************************** @@ -771,6 +848,14 @@ namespace etl { } + //*********************************** + tree_link(tree_link* p_parent, tree_link* p_left, tree_link* p_right) + : etl_parent(p_parent) + , etl_left(p_left) + , etl_right(p_right) + { + } + //*********************************** tree_link(const tree_link& other) : etl_parent(other.etl_parent) @@ -1223,7 +1308,7 @@ namespace etl // Reference template typename etl::enable_if >::value, bool>::type - link_is_linked(TLink& node) + is_linked(TLink& node) { return node.is_linked(); } @@ -1231,9 +1316,9 @@ namespace etl // Pointer template typename etl::enable_if >::value, bool>::type - link_is_linked(TLink* node) + is_linked(TLink* node) { - return node.is_linked(); + return node->is_linked(); } } diff --git a/include/etl/intrusive_list.h b/include/etl/intrusive_list.h index 4a169e3f..28c5dafa 100644 --- a/include/etl/intrusive_list.h +++ b/include/etl/intrusive_list.h @@ -186,6 +186,16 @@ namespace etl //************************************************************************* 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(); } @@ -354,7 +364,7 @@ namespace etl ///\ingroup intrusive_list ///\note TLink must be a base of TValue. //*************************************************************************** - template > + template class intrusive_list : public etl::intrusive_list_base { public: @@ -726,10 +736,17 @@ namespace etl link_type* p_first = const_cast(cp_first); link_type* p_last = const_cast(cp_last); + this->current_size -= etl::distance(first, last); + // Join the ends. etl::link(p_first->etl_previous, p_last); - this->current_size -= etl::distance(first, last); + while (p_first != p_last) + { + link_type* p_next = p_first->etl_next; + p_first->clear(); + p_first = p_next; + } if (p_last == &this->terminal_link) { diff --git a/include/etl/intrusive_queue.h b/include/etl/intrusive_queue.h index eb12b5fe..6e7c1382 100644 --- a/include/etl/intrusive_queue.h +++ b/include/etl/intrusive_queue.h @@ -68,9 +68,23 @@ namespace etl } }; + //*************************************************************************** + /// intrusive_queue_value_is_already_linked exception. + ///\ingroup intrusive_queue + //*************************************************************************** + class intrusive_queue_value_is_already_linked : public intrusive_queue_exception + { + public: + + intrusive_queue_value_is_already_linked(string_type file_name_, numeric_type line_number_) + : intrusive_queue_exception(ETL_ERROR_TEXT("intrusive_queue:value is already linked", ETL_INTRUSIVE_QUEUE_FILE_ID"B"), file_name_, line_number_) + { + } + }; + //*************************************************************************** ///\ingroup queue - /// Base for intrusive queue. Stores elements derived any type that supports an 'etl_next' pointer member. + /// Base for intrusive queue. Stores elements derived any ETL type that supports an 'etl_next' pointer member. /// \tparam TLink The link type that the value is derived from. //*************************************************************************** template @@ -87,21 +101,19 @@ namespace etl //************************************************************************* void push(link_type& value) { - //if (value.is_linked()) - //{ - // return; - //} + ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_queue_value_is_already_linked)); - if (p_back != ETL_NULLPTR) + if (empty()) { - etl::link(p_back, value); + terminator.etl_next = &value; } else { - p_front = &value; + p_back->etl_next = &value; } p_back = &value; + value.etl_next = &terminator; ++current_size; } @@ -113,16 +125,19 @@ namespace etl void pop() { #if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(intrusive_queue_empty)); + ETL_ASSERT_OR_RETURN(!empty(), ETL_ERROR(intrusive_queue_empty)); #endif - link_type* p_next = p_front->etl_next; - p_front->clear(); - p_front = p_next; - // Now empty? - if (p_front == ETL_NULLPTR) + link_type* p_front = terminator.etl_next; + + link_type* p_next = p_front->etl_next; + terminator.etl_next = p_next; + + p_front->clear(); + + if (empty()) { - p_back = ETL_NULLPTR; + p_back = &terminator; } --current_size; @@ -136,7 +151,7 @@ namespace etl template void pop_into(TContainer& destination) { - link_type* p_link = p_front; + link_type* p_link = terminator.etl_next; pop(); destination.push(*p_link); } @@ -176,10 +191,10 @@ namespace etl /// Constructor //************************************************************************* intrusive_queue_base() - : p_front(ETL_NULLPTR), - p_back(ETL_NULLPTR), - current_size(0) + : p_back (&terminator) + , current_size(0) { + terminator.etl_next = &terminator; } //************************************************************************* @@ -189,8 +204,8 @@ namespace etl { } - link_type* p_front; ///< The current front of the queue. - link_type* p_back; ///< The current back of the queue. + link_type* p_back; ///< Pointer to the current back of the queue. + link_type terminator; ///< This link terminates the queue and points to the front of the queue. size_t current_size; ///< Counts the number of elements in the list. }; @@ -233,7 +248,7 @@ namespace etl //************************************************************************* reference front() { - return *static_cast(this->p_front); + return *static_cast(this->terminator.etl_next); } //************************************************************************* @@ -253,7 +268,7 @@ namespace etl //************************************************************************* const_reference front() const { - return *static_cast(this->p_front); + return *static_cast(this->terminator.etl_next); } //************************************************************************* diff --git a/include/etl/intrusive_stack.h b/include/etl/intrusive_stack.h index 267458d9..fe0a123f 100644 --- a/include/etl/intrusive_stack.h +++ b/include/etl/intrusive_stack.h @@ -68,6 +68,20 @@ namespace etl } }; + //*************************************************************************** + /// intrusive_stack_value_is_already_linked exception. + ///\ingroup intrusive_stack + //*************************************************************************** + class intrusive_stack_value_is_already_linked : public intrusive_stack_exception + { + public: + + intrusive_stack_value_is_already_linked(string_type file_name_, numeric_type line_number_) + : intrusive_stack_exception(ETL_ERROR_TEXT("intrusive_stack:value is already linked", ETL_INTRUSIVE_STACK_FILE_ID"B"), file_name_, line_number_) + { + } + }; + //*************************************************************************** ///\ingroup stack /// Base for intrusive stack. Stores elements derived any type that supports an 'etl_next' pointer member. @@ -87,20 +101,11 @@ namespace etl //************************************************************************* void push(link_type& value) { - //if (value.is_linked()) - //{ - // return; - //} - - value.clear(); - - if (p_top != ETL_NULLPTR) - { - etl::link(value, p_top); - } + ETL_ASSERT_OR_RETURN(!value.is_linked(), ETL_ERROR(intrusive_stack_value_is_already_linked)); + value.etl_next = p_top; p_top = &value; - + ++current_size; } @@ -111,9 +116,10 @@ namespace etl void pop() { #if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(intrusive_stack_empty)); + ETL_ASSERT_OR_RETURN(!empty(), ETL_ERROR(intrusive_stack_empty)); #endif link_type* p_next = p_top->etl_next; + p_top->clear(); p_top = p_next; --current_size; } @@ -136,11 +142,11 @@ namespace etl //************************************************************************* void reverse() { - link_type* previous = ETL_NULLPTR; + link_type* previous = &terminator; link_type* current = p_top; link_type* next; - while (current != ETL_NULLPTR) + while (current != &terminator) { next = current->etl_next; current->etl_next = previous; @@ -186,9 +192,9 @@ namespace etl /// Constructor //************************************************************************* intrusive_stack_base() - : p_top(ETL_NULLPTR), - current_size(0) - { + : p_top(&terminator) + , current_size(0) + { } //************************************************************************* @@ -198,7 +204,8 @@ namespace etl { } - link_type* p_top; ///< The current top of the stack. + link_type* p_top; ///< The current top of the stack. + link_type terminator; ///< Terminator link of the queue. size_t current_size; ///< Counts the number of elements in the list. }; diff --git a/include/etl/list.h b/include/etl/list.h index 43497059..c3d0e045 100644 --- a/include/etl/list.h +++ b/include/etl/list.h @@ -869,7 +869,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(etl::forward(args)...); ETL_INCREMENT_DEBUG_COUNT insert_node(get_head(), *p_data_node); @@ -887,7 +887,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1); ETL_INCREMENT_DEBUG_COUNT insert_node(get_head(), *p_data_node); @@ -905,7 +905,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2); ETL_INCREMENT_DEBUG_COUNT insert_node(get_head(), *p_data_node); @@ -923,7 +923,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3); ETL_INCREMENT_DEBUG_COUNT insert_node(get_head(), *p_data_node); @@ -941,7 +941,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3, value4); ETL_INCREMENT_DEBUG_COUNT insert_node(get_head(), *p_data_node); @@ -997,7 +997,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(etl::forward(args)...); ETL_INCREMENT_DEBUG_COUNT insert_node(terminal_node, *p_data_node); @@ -1012,7 +1012,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1); ETL_INCREMENT_DEBUG_COUNT insert_node(terminal_node, *p_data_node); @@ -1027,7 +1027,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2); ETL_INCREMENT_DEBUG_COUNT insert_node(terminal_node, *p_data_node); @@ -1042,7 +1042,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3); ETL_INCREMENT_DEBUG_COUNT insert_node(terminal_node, *p_data_node); @@ -1057,7 +1057,7 @@ namespace etl #endif ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3, value4); ETL_INCREMENT_DEBUG_COUNT insert_node(terminal_node, *p_data_node); @@ -1115,7 +1115,7 @@ namespace etl ETL_ASSERT(!full(), ETL_ERROR(list_full)); ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(etl::forward(args)...); ETL_INCREMENT_DEBUG_COUNT insert_node(*to_iterator(position).p_node, *p_data_node); @@ -1129,7 +1129,7 @@ namespace etl ETL_ASSERT(!full(), ETL_ERROR(list_full)); ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1); ETL_INCREMENT_DEBUG_COUNT insert_node(*position.p_node, *p_data_node); @@ -1143,7 +1143,7 @@ namespace etl ETL_ASSERT(!full(), ETL_ERROR(list_full)); ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2); ETL_INCREMENT_DEBUG_COUNT insert_node(*position.p_node, *p_data_node); @@ -1157,7 +1157,7 @@ namespace etl ETL_ASSERT(!full(), ETL_ERROR(list_full)); ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3); ETL_INCREMENT_DEBUG_COUNT insert_node(*position.p_node, *p_data_node); @@ -1171,7 +1171,7 @@ namespace etl ETL_ASSERT(!full(), ETL_ERROR(list_full)); ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value1, value2, value3, value4); ETL_INCREMENT_DEBUG_COUNT insert_node(*position.p_node, *p_data_node); @@ -1953,7 +1953,7 @@ namespace etl { ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(value); ETL_INCREMENT_DEBUG_COUNT @@ -1968,7 +1968,7 @@ namespace etl { ETL_ASSERT(p_node_pool != ETL_NULLPTR, ETL_ERROR(list_no_pool)); - data_node_t* p_data_node = create_data_node(); + data_node_t* p_data_node = allocate_data_node(); ::new (&(p_data_node->value)) T(etl::move(value)); ETL_INCREMENT_DEBUG_COUNT @@ -1979,7 +1979,7 @@ namespace etl //************************************************************************* /// Create a data_node_t. //************************************************************************* - data_node_t* create_data_node() + data_node_t* allocate_data_node() { data_node_t* (etl::ipool::*func)() = &etl::ipool::allocate; return (p_node_pool->*func)(); diff --git a/include/etl/map.h b/include/etl/map.h index 6e7abb7a..5974573a 100644 --- a/include/etl/map.h +++ b/include/etl/map.h @@ -1496,7 +1496,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node(const_reference value) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new (&node.value) value_type(value); ETL_INCREMENT_DEBUG_COUNT return node; @@ -1507,7 +1507,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node_with_key(const_key_reference key) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new ((void*)etl::addressof(node.value.first)) key_type(key); ::new ((void*)etl::addressof(node.value.second)) mapped_type(); @@ -1521,7 +1521,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node(rvalue_reference value) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new (&node.value) value_type(etl::move(value)); ETL_INCREMENT_DEBUG_COUNT return node; @@ -1532,7 +1532,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node_with_key(rvalue_key_reference key) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new ((void*)etl::addressof(node.value.first)) key_type(etl::move(key)); ::new ((void*)etl::addressof(node.value.second)) mapped_type(); @@ -1545,7 +1545,7 @@ namespace etl //************************************************************************* /// Create a Data_Node. //************************************************************************* - Data_Node& create_data_node() + Data_Node& allocate_data_node() { Data_Node* (etl::ipool::*func)() = &etl::ipool::allocate; return *(p_node_pool->*func)(); diff --git a/include/etl/multimap.h b/include/etl/multimap.h index 2df4d2e0..7e6f71b1 100644 --- a/include/etl/multimap.h +++ b/include/etl/multimap.h @@ -1542,7 +1542,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node(const_reference value) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new (&node.value) const value_type(value); ETL_INCREMENT_DEBUG_COUNT return node; @@ -1554,7 +1554,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node(rvalue_reference value) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new (&node.value) const value_type(etl::move(value)); ETL_INCREMENT_DEBUG_COUNT return node; @@ -1564,7 +1564,7 @@ namespace etl //************************************************************************* /// Create a Data_Node. //************************************************************************* - Data_Node& create_data_node() + Data_Node& allocate_data_node() { Data_Node* (etl::ipool::*func)() = &etl::ipool::allocate; return *(p_node_pool->*func)(); diff --git a/include/etl/multiset.h b/include/etl/multiset.h index 5494792c..0ab3671d 100644 --- a/include/etl/multiset.h +++ b/include/etl/multiset.h @@ -1528,7 +1528,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node(const_reference value) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new ((void*)&node.value) value_type(value); ETL_INCREMENT_DEBUG_COUNT return node; @@ -1540,7 +1540,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node(rvalue_reference value) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new ((void*)&node.value) value_type(etl::move(value)); ETL_INCREMENT_DEBUG_COUNT return node; @@ -1550,7 +1550,7 @@ namespace etl //************************************************************************* /// Create a Data_Node. //************************************************************************* - Data_Node& create_data_node() + Data_Node& allocate_data_node() { Data_Node* (etl::ipool::*func)() = &etl::ipool::allocate; return *(p_node_pool->*func)(); diff --git a/include/etl/set.h b/include/etl/set.h index 9e2b5c4c..e17e6500 100644 --- a/include/etl/set.h +++ b/include/etl/set.h @@ -1361,7 +1361,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node(const_reference value) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new ((void*)&node.value) value_type(value); ETL_INCREMENT_DEBUG_COUNT return node; @@ -1373,7 +1373,7 @@ namespace etl //************************************************************************* Data_Node& allocate_data_node(rvalue_reference value) { - Data_Node& node = create_data_node(); + Data_Node& node = allocate_data_node(); ::new ((void*)&node.value) value_type(etl::move(value)); ETL_INCREMENT_DEBUG_COUNT return node; @@ -1383,7 +1383,7 @@ namespace etl //************************************************************************* /// Create a Data_Node. //************************************************************************* - Data_Node& create_data_node() + Data_Node& allocate_data_node() { Data_Node* (etl::ipool::*func)() = &etl::ipool::allocate; return *(p_node_pool->*func)(); diff --git a/include/etl/unordered_map.h b/include/etl/unordered_map.h index b135079b..77d657b8 100644 --- a/include/etl/unordered_map.h +++ b/include/etl/unordered_map.h @@ -659,7 +659,8 @@ namespace etl // Doesn't exist, so add a new one. // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new ((void*)etl::addressof(node.key_value_pair.first)) key_type(etl::move(key)); ::new ((void*)etl::addressof(node.key_value_pair.second)) mapped_type(); ETL_INCREMENT_DEBUG_COUNT @@ -702,7 +703,8 @@ namespace etl // Doesn't exist, so add a new one. // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new ((void*)etl::addressof(node.key_value_pair.first)) key_type(key); ::new ((void*)etl::addressof(node.key_value_pair.second)) mapped_type(); ETL_INCREMENT_DEBUG_COUNT @@ -833,7 +835,8 @@ namespace etl if (bucket.empty()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new ((void*)etl::addressof(node.key_value_pair)) value_type(key_value_pair); ETL_INCREMENT_DEBUG_COUNT @@ -867,7 +870,8 @@ namespace etl if (inode == bucket.end()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new ((void*)etl::addressof(node.key_value_pair)) value_type(key_value_pair); ETL_INCREMENT_DEBUG_COUNT @@ -909,7 +913,8 @@ namespace etl if (bucket.empty()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new ((void*)etl::addressof(node.key_value_pair)) value_type(etl::move(key_value_pair)); ETL_INCREMENT_DEBUG_COUNT @@ -943,7 +948,8 @@ namespace etl if (inode == bucket.end()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new ((void*)etl::addressof(node.key_value_pair)) value_type(etl::move(key_value_pair)); ETL_INCREMENT_DEBUG_COUNT @@ -1027,12 +1033,8 @@ namespace etl // Did we find it? if (icurrent != bucket.end()) { - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(&bucket); + delete_data_node(iprevious, icurrent, bucket); n = 1; - ETL_DECREMENT_DEBUG_COUNT } return n; @@ -1058,11 +1060,7 @@ namespace etl ++iprevious; } - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(&bucket); - ETL_DECREMENT_DEBUG_COUNT + delete_data_node(iprevious, icurrent, bucket); return inext; } @@ -1096,16 +1094,13 @@ namespace etl ++iprevious; } + // Remember the item before the first erased one. + iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious); + // Until we reach the end. while ((icurrent != iend) || (pbucket != pend_bucket)) - { - local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(pbucket); - ETL_DECREMENT_DEBUG_COUNT - - icurrent = inext; + { + icurrent = delete_data_node(iprevious, icurrent, *pbucket); // Have we not reached the end? if ((icurrent != iend) || (pbucket != pend_bucket)) @@ -1125,7 +1120,7 @@ namespace etl } } - return iterator((pbuckets + number_of_buckets), last_.get_bucket_list_iterator(), last_.get_local_iterator()); + return ++ibefore_erased; } //************************************************************************* @@ -1442,7 +1437,7 @@ namespace etl //************************************************************************* /// Create a node. //************************************************************************* - node_t& create_data_node() + node_t& allocate_data_node() { node_t* (etl::ipool::*func)() = &etl::ipool::allocate; return *(pnodepool->*func)(); @@ -1512,6 +1507,20 @@ namespace etl } } + //********************************************************************* + /// Delete a data noe at the specified location. + //********************************************************************* + local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket) + { + local_iterator inext = bucket.erase_after(iprevious); // Unlink from the bucket. + icurrent->key_value_pair.~value_type(); // Destroy the value. + pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); + ETL_DECREMENT_DEBUG_COUNT + + return inext; + } + // Disable copy construction. iunordered_map(const iunordered_map&); diff --git a/include/etl/unordered_multimap.h b/include/etl/unordered_multimap.h index 566ff291..07a1d12f 100644 --- a/include/etl/unordered_multimap.h +++ b/include/etl/unordered_multimap.h @@ -675,7 +675,8 @@ namespace etl if (bucket.empty()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key_value_pair) value_type(key_value_pair); ETL_INCREMENT_DEBUG_COUNT @@ -704,7 +705,8 @@ namespace etl } // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key_value_pair) value_type(key_value_pair); ETL_INCREMENT_DEBUG_COUNT @@ -744,7 +746,8 @@ namespace etl if (bucket.empty()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key_value_pair) value_type(etl::move(key_value_pair)); ETL_INCREMENT_DEBUG_COUNT @@ -773,7 +776,8 @@ namespace etl } // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key_value_pair) value_type(etl::move(key_value_pair)); ETL_INCREMENT_DEBUG_COUNT @@ -849,13 +853,9 @@ namespace etl { if (key_equal_function(icurrent->key_value_pair.first, key)) { - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(&bucket); + delete_data_node(iprevious, icurrent, bucket); ++n; icurrent = iprevious; - ETL_DECREMENT_DEBUG_COUNT } else { @@ -888,11 +888,7 @@ namespace etl ++iprevious; } - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(&bucket); - ETL_DECREMENT_DEBUG_COUNT + delete_data_node(iprevious, icurrent, bucket); return inext; } @@ -913,9 +909,6 @@ namespace etl return end(); } - // Make a note of the last. - iterator result((pbuckets + number_of_buckets), last_.get_bucket_list_iterator(), last_.get_local_iterator()); - // Get the starting point. bucket_t* pbucket = first_.get_bucket_list_iterator(); bucket_t* pend_bucket = last_.get_bucket_list_iterator(); @@ -929,17 +922,13 @@ namespace etl ++iprevious; } + // Remember the item before the first erased one. + iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious); + // Until we reach the end. while ((icurrent != iend) || (pbucket != pend_bucket)) { - - local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. - icurrent->key_value_pair.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(pbucket); - ETL_DECREMENT_DEBUG_COUNT - - icurrent = inext; + icurrent = delete_data_node(iprevious, icurrent, *pbucket); // Have we not reached the end? if ((icurrent != iend) || (pbucket != pend_bucket)) @@ -959,7 +948,7 @@ namespace etl } } - return result; + return ++ibefore_erased; } //************************************************************************* @@ -1302,7 +1291,7 @@ namespace etl //************************************************************************* /// Create a node. //************************************************************************* - node_t& create_data_node() + node_t& allocate_data_node() { node_t* (etl::ipool::*func)() = &etl::ipool::allocate; return *(pnodepool->*func)(); @@ -1372,6 +1361,20 @@ namespace etl } } + //********************************************************************* + /// Delete a data noe at the specified location. + //********************************************************************* + local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket) + { + local_iterator inext = bucket.erase_after(iprevious); // Unlink from the bucket. + icurrent->key_value_pair.~value_type(); // Destroy the value. + pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); + ETL_DECREMENT_DEBUG_COUNT + + return inext; + } + // Disable copy construction. iunordered_multimap(const iunordered_multimap&); diff --git a/include/etl/unordered_multiset.h b/include/etl/unordered_multiset.h index 1821d6e8..973bf402 100644 --- a/include/etl/unordered_multiset.h +++ b/include/etl/unordered_multiset.h @@ -664,7 +664,8 @@ namespace etl if (bucket.empty()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key) value_type(key); ETL_INCREMENT_DEBUG_COUNT @@ -694,7 +695,8 @@ namespace etl } // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key) value_type(key); ETL_INCREMENT_DEBUG_COUNT @@ -733,7 +735,8 @@ namespace etl if (bucket.empty()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key) value_type(etl::move(key)); ETL_INCREMENT_DEBUG_COUNT @@ -763,7 +766,8 @@ namespace etl } // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key) value_type(etl::move(key)); ETL_INCREMENT_DEBUG_COUNT @@ -827,13 +831,9 @@ namespace etl { if (key_equal_function(icurrent->key, key)) { - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(&bucket); + delete_data_node(iprevious, icurrent, bucket); ++n; icurrent = iprevious; - ETL_DECREMENT_DEBUG_COUNT } else { @@ -866,11 +866,7 @@ namespace etl ++iprevious; } - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(&bucket); - ETL_DECREMENT_DEBUG_COUNT + delete_data_node(iprevious, icurrent, bucket); return inext; } @@ -891,9 +887,6 @@ namespace etl return end(); } - // Make a note of the last. - iterator result((pbuckets + number_of_buckets), last_.get_bucket_list_iterator(), last_.get_local_iterator()); - // Get the starting point. bucket_t* pbucket = first_.get_bucket_list_iterator(); bucket_t* pend_bucket = last_.get_bucket_list_iterator(); @@ -907,17 +900,13 @@ namespace etl ++iprevious; } + // Remember the item before the first erased one. + iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious); + // Until we reach the end. while ((icurrent != iend) || (pbucket != pend_bucket)) { - - local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(pbucket); - ETL_DECREMENT_DEBUG_COUNT - - icurrent = inext; + icurrent = delete_data_node(iprevious, icurrent, *pbucket); // Have we not reached the end? if ((icurrent != iend) || (pbucket != pend_bucket)) @@ -937,7 +926,7 @@ namespace etl } } - return result; + return ++ibefore_erased; } //************************************************************************* @@ -1280,7 +1269,7 @@ namespace etl //************************************************************************* /// Create a node. //************************************************************************* - node_t& create_data_node() + node_t& allocate_data_node() { node_t* (etl::ipool::*func)() = &etl::ipool::allocate; return *(pnodepool->*func)(); @@ -1350,6 +1339,20 @@ namespace etl } } + //********************************************************************* + /// Delete a data noe at the specified location. + //********************************************************************* + local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket) + { + local_iterator inext = bucket.erase_after(iprevious); // Unlink from the bucket. + icurrent->key.~value_type(); // Destroy the value. + pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); + ETL_DECREMENT_DEBUG_COUNT + + return inext; + } + // Disable copy construction. iunordered_multiset(const iunordered_multiset&); diff --git a/include/etl/unordered_set.h b/include/etl/unordered_set.h index 3a729c66..10a3f3ad 100644 --- a/include/etl/unordered_set.h +++ b/include/etl/unordered_set.h @@ -665,7 +665,8 @@ namespace etl if (bucket.empty()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key) value_type(key); ETL_INCREMENT_DEBUG_COUNT @@ -698,7 +699,8 @@ namespace etl if (inode == bucket.end()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key) value_type(key); ETL_INCREMENT_DEBUG_COUNT @@ -738,7 +740,8 @@ namespace etl if (bucket.empty()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key) value_type(etl::move(key)); ETL_INCREMENT_DEBUG_COUNT @@ -771,7 +774,8 @@ namespace etl if (inode == bucket.end()) { // Get a new node. - node_t& node = create_data_node(); + node_t& node = allocate_data_node(); + node.clear(); ::new (&node.key) value_type(etl::move(key)); ETL_INCREMENT_DEBUG_COUNT @@ -855,12 +859,8 @@ namespace etl // Did we find it? if (icurrent != bucket.end()) { - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(&bucket); + delete_data_node(iprevious, icurrent, bucket); n = 1; - ETL_DECREMENT_DEBUG_COUNT } return n; @@ -886,11 +886,7 @@ namespace etl ++iprevious; } - bucket.erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(&bucket); - ETL_DECREMENT_DEBUG_COUNT + delete_data_node(iprevious, icurrent, bucket); return inext; } @@ -911,9 +907,6 @@ namespace etl return end(); } - // Make a note of the last. - iterator result((pbuckets + number_of_buckets), last_.get_bucket_list_iterator(), last_.get_local_iterator()); - // Get the starting point. bucket_t* pbucket = first_.get_bucket_list_iterator(); bucket_t* pend_bucket = last_.get_bucket_list_iterator(); @@ -927,17 +920,13 @@ namespace etl ++iprevious; } + // Remember the item before the first erased one. + iterator ibefore_erased = iterator((pbuckets + number_of_buckets), pbucket, iprevious); + // Until we reach the end. while ((icurrent != iend) || (pbucket != pend_bucket)) { - - local_iterator inext = pbucket->erase_after(iprevious); // Unlink from the bucket. - icurrent->key.~value_type(); // Destroy the value. - pnodepool->release(&*icurrent); // Release it back to the pool. - adjust_first_last_markers_after_erase(pbucket); - ETL_DECREMENT_DEBUG_COUNT - - icurrent = inext; + icurrent = delete_data_node(iprevious, icurrent, *pbucket); // Have we not reached the end? if ((icurrent != iend) || (pbucket != pend_bucket)) @@ -957,7 +946,7 @@ namespace etl } } - return result; + return ++ibefore_erased; } //************************************************************************* @@ -1280,7 +1269,7 @@ namespace etl //************************************************************************* /// Create a node. //************************************************************************* - node_t& create_data_node() + node_t& allocate_data_node() { node_t* (etl::ipool::*func)() = &etl::ipool::allocate; return *(pnodepool->*func)(); @@ -1314,40 +1303,54 @@ namespace etl //********************************************************************* void adjust_first_last_markers_after_erase(bucket_t* pcurrent) { -if (empty()) -{ - first = pbuckets; - last = pbuckets; -} -else -{ - if (pcurrent == first) - { - // We erased the first so, we need to search again from where we erased. - while (first->empty()) - { - ++first; - } - } - else if (pcurrent == last) - { - // We erased the last, so we need to search again. Start from the first, go no further than the current last. - bucket_t* pcurrent = first; - bucket_t* pend = last; - - last = first; - - while (pcurrent != pend) - { - if (!pcurrent->empty()) + if (empty()) { - last = pcurrent; + first = pbuckets; + last = pbuckets; } + else + { + if (pcurrent == first) + { + // We erased the first so, we need to search again from where we erased. + while (first->empty()) + { + ++first; + } + } + else if (pcurrent == last) + { + // We erased the last, so we need to search again. Start from the first, go no further than the current last. + bucket_t* pcurrent = first; + bucket_t* pend = last; - ++pcurrent; + last = first; + + while (pcurrent != pend) + { + if (!pcurrent->empty()) + { + last = pcurrent; + } + + ++pcurrent; + } + } + } } - } -} + + //********************************************************************* + /// Delete a data noe at the specified location. + //********************************************************************* + local_iterator delete_data_node(local_iterator iprevious, local_iterator icurrent, bucket_t& bucket) + { + local_iterator inext = bucket.erase_after(iprevious); // Unlink from the bucket. + icurrent->key.~value_type(); // Destroy the value. + pnodepool->release(&*icurrent); // Release it back to the pool. + adjust_first_last_markers_after_erase(&bucket); + ETL_DECREMENT_DEBUG_COUNT + + return inext; } // Disable copy construction. diff --git a/support/Release notes.txt b/support/Release notes.txt index fd9fd08d..e3c6f61e 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -8,6 +8,7 @@ #712 Unable to use etl::optional with non-default-constructible POD objects. Modified etl::visitor to allow direct specification of the argument type. Added etl::is_visitor trait. +Removed default link type for etl::intrusive_list and etl::intrusive_forward_list =============================================================================== 20.36.2 diff --git a/test/test_intrusive_forward_list.cpp b/test/test_intrusive_forward_list.cpp index 04a87f8c..3dab02b4 100644 --- a/test/test_intrusive_forward_list.cpp +++ b/test/test_intrusive_forward_list.cpp @@ -253,8 +253,19 @@ namespace TEST_FIXTURE(SetupFixture, test_clear) { DataNDC0 data0(sorted_data.begin(), sorted_data.end()); + + for (auto& item : sorted_data) + { + CHECK_TRUE(etl::is_linked(item)); + } + data0.clear(); + for (auto& item : sorted_data) + { + CHECK_FALSE(etl::is_linked(item)); + } + CHECK(data0.empty()); } @@ -263,11 +274,13 @@ namespace { DataNDC0 data0; + static InitialDataNDC sorted_data = { ItemNDCNode("0"), ItemNDCNode("1"), ItemNDCNode("2"), ItemNDCNode("3"), ItemNDCNode("4"), ItemNDCNode("5"), ItemNDCNode("6"), ItemNDCNode("7"), ItemNDCNode("8"), ItemNDCNode("9") }; + // Do it twice. We should only get one copy. data0.assign(sorted_data.begin(), sorted_data.end()); data0.assign(sorted_data.begin(), sorted_data.end()); - are_equal = std::equal(data0.begin(), data0.end(), sorted_data.begin()); + bool are_equal = std::equal(data0.begin(), data0.end(), sorted_data.begin()); CHECK(are_equal); } @@ -276,7 +289,7 @@ namespace TEST_FIXTURE(SetupFixture, test_assign_range_two_lists_same) { DataNDC0 data0; - DataNDC0 data1; + DataNDC1 data1; data0.assign(sorted_data.begin(), sorted_data.end()); data1.assign(sorted_data.begin(), sorted_data.end()); @@ -596,6 +609,17 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_after_range) { + FirstLink& fl0 = sorted_data[0]; + FirstLink& fl1 = sorted_data[1]; + FirstLink& fl2 = sorted_data[2]; + FirstLink& fl3 = sorted_data[3]; + FirstLink& fl4 = sorted_data[4]; + FirstLink& fl5 = sorted_data[5]; + FirstLink& fl6 = sorted_data[6]; + FirstLink& fl7 = sorted_data[7]; + FirstLink& fl8 = sorted_data[8]; + FirstLink& fl9 = sorted_data[9]; + std::forward_list compare_data(sorted_data.begin(), sorted_data.end()); DataNDC0 data0(sorted_data.begin(), sorted_data.end()); DataNDC1 data1(sorted_data2.begin(), sorted_data2.end()); @@ -614,8 +638,30 @@ namespace std::forward_list::iterator i_compare_result = compare_data.erase_after(i_compare_data_1, i_compare_data_2); + CHECK_TRUE(fl0.is_linked()); + CHECK_TRUE(fl1.is_linked()); + CHECK_TRUE(fl2.is_linked()); + CHECK_TRUE(fl3.is_linked()); + CHECK_TRUE(fl4.is_linked()); + CHECK_TRUE(fl5.is_linked()); + CHECK_TRUE(fl6.is_linked()); + CHECK_TRUE(fl7.is_linked()); + CHECK_TRUE(fl8.is_linked()); + CHECK_TRUE(fl9.is_linked()); + DataNDC0::iterator i_result = data0.erase_after(i_data_1, i_data_2); + CHECK_TRUE(fl0.is_linked()); + CHECK_TRUE(fl1.is_linked()); + CHECK_TRUE(fl2.is_linked()); + CHECK_FALSE(fl3.is_linked()); + CHECK_FALSE(fl4.is_linked()); + CHECK_TRUE(fl5.is_linked()); + CHECK_TRUE(fl6.is_linked()); + CHECK_TRUE(fl7.is_linked()); + CHECK_TRUE(fl8.is_linked()); + CHECK_TRUE(fl9.is_linked()); + CHECK_EQUAL(*i_compare_result, *i_result); are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin()); @@ -748,11 +794,46 @@ namespace DataNDC0 data0(sorted_data.begin(), sorted_data.end()); DataNDC1 data1(sorted_data.begin(), sorted_data.end()); + FirstLink& fl0 = sorted_data[0]; + FirstLink& fl1 = sorted_data[1]; + FirstLink& fl2 = sorted_data[2]; + FirstLink& fl3 = sorted_data[3]; + FirstLink& fl4 = sorted_data[4]; + FirstLink& fl5 = sorted_data[5]; + FirstLink& fl6 = sorted_data[6]; + FirstLink& fl7 = sorted_data[7]; + FirstLink& fl8 = sorted_data[8]; + FirstLink& fl9 = sorted_data[9]; + + CHECK_TRUE(fl0.etl_next == &fl1); + CHECK_TRUE(fl1.etl_next == &fl2); + CHECK_TRUE(fl2.etl_next == &fl3); + CHECK_TRUE(fl3.etl_next == &fl4); + CHECK_TRUE(fl4.etl_next == &fl5); + CHECK_TRUE(fl5.etl_next == &fl6); + CHECK_TRUE(fl6.etl_next == &fl7); + CHECK_TRUE(fl7.etl_next == &fl8); + CHECK_TRUE(fl8.etl_next == &fl9); + CHECK_TRUE(fl9.etl_next == &(*data0.end())); + data0.reverse(); // Just reverse one of them. + CHECK_TRUE(fl9.etl_next == &fl8); + CHECK_TRUE(fl8.etl_next == &fl7); + CHECK_TRUE(fl7.etl_next == &fl6); + CHECK_TRUE(fl6.etl_next == &fl5); + CHECK_TRUE(fl5.etl_next == &fl4); + CHECK_TRUE(fl4.etl_next == &fl3); + CHECK_TRUE(fl3.etl_next == &fl2); + CHECK_TRUE(fl2.etl_next == &fl1); + CHECK_TRUE(fl1.etl_next == &fl0); + CHECK_TRUE(fl0.etl_next == &(*data0.end())); + CHECK_EQUAL(data1.size(), data0.size()); CHECK_EQUAL(data0.size(), size_t(std::distance(data0.begin(), data0.end()))); + bool are_equal = false; + are_equal = std::equal(data0.begin(), data0.end(), sorted_data.rbegin()); CHECK(are_equal); @@ -811,7 +892,7 @@ namespace CHECK(are_equal); } - //************************************************************************* + ////************************************************************************* TEST_FIXTURE(SetupFixture, test_splice_list) { DataNDC0 data0(sorted_data.begin(), sorted_data.end()); diff --git a/test/test_intrusive_links.cpp b/test/test_intrusive_links.cpp index 829f1b19..13a09c5b 100644 --- a/test/test_intrusive_links.cpp +++ b/test/test_intrusive_links.cpp @@ -106,19 +106,19 @@ namespace FData data2(2); FData data3(3); - data0.FLink0::clear(); + etl::link_clear(data0); etl::link(data0, data1); CHECK(data0.FLink0::etl_next == &data1); - data0.FLink0::clear(); + etl::link_clear(data0); etl::link(&data0, data1); CHECK(data0.FLink0::etl_next == &data1); - data0.FLink0::clear(); + etl::link_clear(data0); etl::link(data0, &data1); CHECK(data0.FLink0::etl_next == &data1); - data0.FLink0::clear(); + etl::link_clear(data0); etl::link(&data0, &data1); CHECK(data0.FLink0::etl_next == &data1); @@ -390,7 +390,7 @@ namespace FLink0* start = etl::unlink_after(data0, data2); CHECK(data0.FLink0::etl_next == &data3); CHECK(data1.FLink0::etl_next == &data2); - CHECK(data2.FLink0::etl_next == &data3); + CHECK(data2.FLink0::etl_next == nullptr); CHECK(data3.FLink0::etl_next == nullptr); etl::link_clear_range(*start); @@ -416,7 +416,7 @@ namespace etl::unlink_after(data0); - CHECK(data0.FLink0::etl_next == &data0); + CHECK(data0.FLink0::etl_next == nullptr); } //************************************************************************* diff --git a/test/test_intrusive_list.cpp b/test/test_intrusive_list.cpp index 66750b0d..b15ceb10 100644 --- a/test/test_intrusive_list.cpp +++ b/test/test_intrusive_list.cpp @@ -267,10 +267,123 @@ namespace //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { + FirstLink& fl0 = sorted_data[0]; + FirstLink& fl1 = sorted_data[1]; + FirstLink& fl2 = sorted_data[2]; + FirstLink& fl3 = sorted_data[3]; + FirstLink& fl4 = sorted_data[4]; + FirstLink& fl5 = sorted_data[5]; + FirstLink& fl6 = sorted_data[6]; + FirstLink& fl7 = sorted_data[7]; + FirstLink& fl8 = sorted_data[8]; + FirstLink& fl9 = sorted_data[9]; + + SecondLink& sl0 = sorted_data[0]; + SecondLink& sl1 = sorted_data[1]; + SecondLink& sl2 = sorted_data[2]; + SecondLink& sl3 = sorted_data[3]; + SecondLink& sl4 = sorted_data[4]; + SecondLink& sl5 = sorted_data[5]; + SecondLink& sl6 = sorted_data[6]; + SecondLink& sl7 = sorted_data[7]; + SecondLink& sl8 = sorted_data[8]; + SecondLink& sl9 = sorted_data[9]; + DataNDC0 data0(sorted_data.begin(), sorted_data.end()); + + CHECK_TRUE(fl0.is_linked()); + CHECK_TRUE(fl1.is_linked()); + CHECK_TRUE(fl2.is_linked()); + CHECK_TRUE(fl3.is_linked()); + CHECK_TRUE(fl4.is_linked()); + CHECK_TRUE(fl5.is_linked()); + CHECK_TRUE(fl6.is_linked()); + CHECK_TRUE(fl7.is_linked()); + CHECK_TRUE(fl8.is_linked()); + CHECK_TRUE(fl9.is_linked()); + + CHECK_FALSE(sl0.is_linked()); + CHECK_FALSE(sl1.is_linked()); + CHECK_FALSE(sl2.is_linked()); + CHECK_FALSE(sl3.is_linked()); + CHECK_FALSE(sl4.is_linked()); + CHECK_FALSE(sl5.is_linked()); + CHECK_FALSE(sl6.is_linked()); + CHECK_FALSE(sl7.is_linked()); + CHECK_FALSE(sl8.is_linked()); + CHECK_FALSE(sl9.is_linked()); + + DataNDC1 data1(sorted_data.begin(), sorted_data.end()); + + CHECK_TRUE(fl0.is_linked()); + CHECK_TRUE(fl1.is_linked()); + CHECK_TRUE(fl2.is_linked()); + CHECK_TRUE(fl3.is_linked()); + CHECK_TRUE(fl4.is_linked()); + CHECK_TRUE(fl5.is_linked()); + CHECK_TRUE(fl6.is_linked()); + CHECK_TRUE(fl7.is_linked()); + CHECK_TRUE(fl8.is_linked()); + CHECK_TRUE(fl9.is_linked()); + + CHECK_TRUE(sl0.is_linked()); + CHECK_TRUE(sl1.is_linked()); + CHECK_TRUE(sl2.is_linked()); + CHECK_TRUE(sl3.is_linked()); + CHECK_TRUE(sl4.is_linked()); + CHECK_TRUE(sl5.is_linked()); + CHECK_TRUE(sl6.is_linked()); + CHECK_TRUE(sl7.is_linked()); + CHECK_TRUE(sl8.is_linked()); + CHECK_TRUE(sl9.is_linked()); + data0.clear(); - CHECK(data0.empty()); + CHECK_FALSE(fl0.is_linked()); + CHECK_FALSE(fl1.is_linked()); + CHECK_FALSE(fl2.is_linked()); + CHECK_FALSE(fl3.is_linked()); + CHECK_FALSE(fl4.is_linked()); + CHECK_FALSE(fl5.is_linked()); + CHECK_FALSE(fl6.is_linked()); + CHECK_FALSE(fl7.is_linked()); + CHECK_FALSE(fl8.is_linked()); + CHECK_FALSE(fl9.is_linked()); + + CHECK_TRUE(sl0.is_linked()); + CHECK_TRUE(sl1.is_linked()); + CHECK_TRUE(sl2.is_linked()); + CHECK_TRUE(sl3.is_linked()); + CHECK_TRUE(sl4.is_linked()); + CHECK_TRUE(sl5.is_linked()); + CHECK_TRUE(sl6.is_linked()); + CHECK_TRUE(sl7.is_linked()); + CHECK_TRUE(sl8.is_linked()); + CHECK_TRUE(sl9.is_linked()); + + data1.clear(); + + CHECK_FALSE(fl0.is_linked()); + CHECK_FALSE(fl1.is_linked()); + CHECK_FALSE(fl2.is_linked()); + CHECK_FALSE(fl3.is_linked()); + CHECK_FALSE(fl4.is_linked()); + CHECK_FALSE(fl5.is_linked()); + CHECK_FALSE(fl6.is_linked()); + CHECK_FALSE(fl7.is_linked()); + CHECK_FALSE(fl8.is_linked()); + CHECK_FALSE(fl9.is_linked()); + + CHECK_FALSE(sl0.is_linked()); + CHECK_FALSE(sl1.is_linked()); + CHECK_FALSE(sl2.is_linked()); + CHECK_FALSE(sl3.is_linked()); + CHECK_FALSE(sl4.is_linked()); + CHECK_FALSE(sl5.is_linked()); + CHECK_FALSE(sl6.is_linked()); + CHECK_FALSE(sl7.is_linked()); + CHECK_FALSE(sl8.is_linked()); + CHECK_FALSE(sl9.is_linked()); } //************************************************************************* @@ -626,6 +739,28 @@ namespace { bool are_equal; + FirstLink& fl0 = sorted_data[0]; + FirstLink& fl1 = sorted_data[1]; + FirstLink& fl2 = sorted_data[2]; + FirstLink& fl3 = sorted_data[3]; + FirstLink& fl4 = sorted_data[4]; + FirstLink& fl5 = sorted_data[5]; + FirstLink& fl6 = sorted_data[6]; + FirstLink& fl7 = sorted_data[7]; + FirstLink& fl8 = sorted_data[8]; + FirstLink& fl9 = sorted_data[9]; + + SecondLink& sl0 = sorted_data[0]; + SecondLink& sl1 = sorted_data[1]; + SecondLink& sl2 = sorted_data[2]; + SecondLink& sl3 = sorted_data[3]; + SecondLink& sl4 = sorted_data[4]; + SecondLink& sl5 = sorted_data[5]; + SecondLink& sl6 = sorted_data[6]; + SecondLink& sl7 = sorted_data[7]; + SecondLink& sl8 = sorted_data[8]; + SecondLink& sl9 = sorted_data[9]; + std::vector compare_data(sorted_data.begin(), sorted_data.end()); DataNDC0 data0(sorted_data.begin(), sorted_data.end()); DataNDC1 data1(sorted_data.begin(), sorted_data.end()); @@ -634,18 +769,40 @@ namespace std::advance(i_data_1, 3); DataNDC0::iterator i_data_2 = data0.begin(); - std::advance(i_data_2, 4); + std::advance(i_data_2, 7); std::vector::iterator i_compare_data_1 = compare_data.begin(); std::advance(i_compare_data_1, 3); std::vector::iterator i_compare_data_2 = compare_data.begin(); - std::advance(i_compare_data_2, 4); + std::advance(i_compare_data_2, 7); std::vector::iterator i_compare_result = compare_data.erase(i_compare_data_1, i_compare_data_2); DataNDC0::iterator i_result = data0.erase(i_data_1, i_data_2); + CHECK_TRUE(fl0.is_linked()); + CHECK_TRUE(fl1.is_linked()); + CHECK_TRUE(fl2.is_linked()); + CHECK_FALSE(fl3.is_linked()); + CHECK_FALSE(fl4.is_linked()); + CHECK_FALSE(fl5.is_linked()); + CHECK_FALSE(fl6.is_linked()); + CHECK_TRUE(fl7.is_linked()); + CHECK_TRUE(fl8.is_linked()); + CHECK_TRUE(fl9.is_linked()); + + CHECK_TRUE(sl0.is_linked()); + CHECK_TRUE(sl1.is_linked()); + CHECK_TRUE(sl2.is_linked()); + CHECK_TRUE(sl3.is_linked()); + CHECK_TRUE(sl4.is_linked()); + CHECK_TRUE(sl5.is_linked()); + CHECK_TRUE(sl6.is_linked()); + CHECK_TRUE(sl7.is_linked()); + CHECK_TRUE(sl8.is_linked()); + CHECK_TRUE(sl9.is_linked()); + CHECK_EQUAL(*i_compare_result, *i_result); are_equal = std::equal(data0.begin(), data0.end(), compare_data.begin()); diff --git a/test/test_intrusive_queue.cpp b/test/test_intrusive_queue.cpp index f8ee1ba3..8b44f343 100644 --- a/test/test_intrusive_queue.cpp +++ b/test/test_intrusive_queue.cpp @@ -138,10 +138,30 @@ namespace queueC.push(data2); queueD.clear(); + + CHECK_TRUE(queueD.empty()); + CHECK_FALSE(queueC.empty()); + + CHECK_FALSE(etl::is_linked(data1)); + CHECK_FALSE(etl::is_linked(data2)); + CHECK_FALSE(etl::is_linked(data3)); + + CHECK_TRUE(etl::is_linked(data1)); + CHECK_TRUE(etl::is_linked(data2)); + CHECK_FALSE(etl::is_linked(data3)); + queueC.clear(); - CHECK(queueD.empty()); - CHECK(queueC.empty()); + CHECK_FALSE(etl::is_linked(data1)); + CHECK_FALSE(etl::is_linked(data2)); + CHECK_FALSE(etl::is_linked(data3)); + + CHECK_FALSE(etl::is_linked(data1)); + CHECK_FALSE(etl::is_linked(data2)); + CHECK_FALSE(etl::is_linked(data3)); + + CHECK_TRUE(queueD.empty()); + CHECK_TRUE(queueC.empty()); } //************************************************************************* @@ -186,34 +206,34 @@ namespace etl::intrusive_queue queue; queue.push(data1); - CHECK(data1.link_fwd::etl_next == ETL_NULLPTR); - CHECK(data2.link_fwd::etl_next == ETL_NULLPTR); - CHECK(data3.link_fwd::etl_next == ETL_NULLPTR); - CHECK(data4.link_fwd::etl_next == ETL_NULLPTR); + CHECK_TRUE(data1.link_fwd::is_linked()); + CHECK_FALSE(data2.link_fwd::is_linked()); + CHECK_FALSE(data3.link_fwd::is_linked()); + CHECK_FALSE(data4.link_fwd::is_linked()); queue.push(data2); - CHECK(data1.link_fwd::etl_next == &data2); - CHECK(data2.link_fwd::etl_next == ETL_NULLPTR); - CHECK(data3.link_fwd::etl_next == ETL_NULLPTR); - CHECK(data4.link_fwd::etl_next == ETL_NULLPTR); + CHECK_TRUE(data1.link_fwd::is_linked()); + CHECK_TRUE(data2.link_fwd::is_linked()); + CHECK_FALSE(data3.link_fwd::is_linked()); + CHECK_FALSE(data4.link_fwd::is_linked()); queue.push(data3); - CHECK(data1.link_fwd::etl_next == &data2); - CHECK(data2.link_fwd::etl_next == &data3); - CHECK(data3.link_fwd::etl_next == ETL_NULLPTR); - CHECK(data4.link_fwd::etl_next == ETL_NULLPTR); + CHECK_TRUE(data1.link_fwd::is_linked()); + CHECK_TRUE(data2.link_fwd::is_linked()); + CHECK_TRUE(data3.link_fwd::is_linked()); + CHECK_FALSE(data4.link_fwd::is_linked()); - queue.push(data2); - CHECK(data1.link_fwd::etl_next == &data2); - CHECK(data2.link_fwd::etl_next == &data3); - CHECK(data3.link_fwd::etl_next == ETL_NULLPTR); - CHECK(data4.link_fwd::etl_next == ETL_NULLPTR); + CHECK_THROW(queue.push(data2), etl::intrusive_queue_value_is_already_linked); + CHECK_TRUE(data1.link_fwd::is_linked()); + CHECK_TRUE(data2.link_fwd::is_linked()); + CHECK_TRUE(data3.link_fwd::is_linked()); + CHECK_FALSE(data4.link_fwd::is_linked()); queue.push(data4); - CHECK(data1.link_fwd::etl_next == &data2); - CHECK(data2.link_fwd::etl_next == &data3); - CHECK(data3.link_fwd::etl_next == &data4); - CHECK(data4.link_fwd::etl_next == ETL_NULLPTR); + CHECK_TRUE(data1.link_fwd::is_linked()); + CHECK_TRUE(data2.link_fwd::is_linked()); + CHECK_TRUE(data3.link_fwd::is_linked()); + CHECK_TRUE(data4.link_fwd::is_linked()); CHECK_EQUAL(4, queue.size()); } @@ -238,20 +258,25 @@ namespace CHECK_EQUAL(queueD.front(), data1); CHECK_EQUAL(queueD.back(), data3); queueD.pop(); + CHECK_FALSE(data1.link_fwd::is_linked()); CHECK_EQUAL(queueD.front(), data2); CHECK_EQUAL(queueD.back(), data3); queueD.pop(); + CHECK_FALSE(data2.link_fwd::is_linked()); CHECK_EQUAL(queueD.front(), data3); CHECK_EQUAL(queueD.back(), data3); queueD.pop(); + CHECK_FALSE(data3.link_fwd::is_linked()); CHECK(queueD.empty()); CHECK_EQUAL(queueC.front(), data1); CHECK_EQUAL(queueC.back(), data2); queueC.pop(); + CHECK_FALSE(data1.link_bdir::is_linked()); CHECK_EQUAL(queueC.front(), data2); CHECK_EQUAL(queueC.back(), data2); queueC.pop(); + CHECK_FALSE(data2.link_bdir::is_linked()); CHECK(queueC.empty()); } @@ -266,10 +291,22 @@ namespace etl::intrusive_queue queue2; queue1.push(data1); + CHECK_TRUE(data1.link_fwd::is_linked()); + CHECK_FALSE(data2.link_fwd::is_linked()); + CHECK_FALSE(data3.link_fwd::is_linked()); + queue1.push(data2); + CHECK_TRUE(data1.link_fwd::is_linked()); + CHECK_TRUE(data2.link_fwd::is_linked()); + CHECK_FALSE(data3.link_fwd::is_linked()); + queue1.push(data3); + CHECK_TRUE(data1.link_fwd::is_linked()); + CHECK_TRUE(data2.link_fwd::is_linked()); + CHECK_TRUE(data3.link_fwd::is_linked()); queue1.pop_into(queue2); + CHECK_TRUE(data1.link_fwd::is_linked()); CHECK_EQUAL(2U, queue1.size()); CHECK_EQUAL(data2, queue1.front()); @@ -278,6 +315,7 @@ namespace CHECK_EQUAL(data1, queue2.back()); queue1.pop_into(queue2); + CHECK_TRUE(data2.link_fwd::is_linked()); CHECK_EQUAL(1U, queue1.size()); CHECK_EQUAL(data3, queue1.front()); @@ -286,6 +324,7 @@ namespace CHECK_EQUAL(data2, queue2.back()); queue1.pop_into(queue2); + CHECK_TRUE(data3.link_fwd::is_linked()); CHECK_EQUAL(0U, queue1.size()); CHECK_EQUAL(3U, queue2.size()); @@ -305,24 +344,24 @@ namespace queue.push(data1); queue.push(data2); queue.push(data3); - CHECK_TRUE(data1.link_fwd::etl_next != ETL_NULLPTR); - CHECK_TRUE(data2.link_fwd::etl_next != ETL_NULLPTR); - CHECK_TRUE(data3.link_fwd::etl_next == ETL_NULLPTR); + CHECK_TRUE(data1.link_fwd::is_linked()); + CHECK_TRUE(data2.link_fwd::is_linked()); + CHECK_TRUE(data3.link_fwd::is_linked()); queue.pop(); - CHECK_TRUE(data1.link_fwd::etl_next == ETL_NULLPTR); - CHECK_TRUE(data2.link_fwd::etl_next != ETL_NULLPTR); - CHECK_TRUE(data3.link_fwd::etl_next == ETL_NULLPTR); + CHECK_FALSE(data1.link_fwd::is_linked()); + CHECK_TRUE(data2.link_fwd::is_linked()); + CHECK_TRUE(data3.link_fwd::is_linked()); queue.pop(); - CHECK_TRUE(data1.link_fwd::etl_next == ETL_NULLPTR); - CHECK_TRUE(data2.link_fwd::etl_next == ETL_NULLPTR); - CHECK_TRUE(data3.link_fwd::etl_next == ETL_NULLPTR); + CHECK_FALSE(data1.link_fwd::is_linked()); + CHECK_FALSE(data2.link_fwd::is_linked()); + CHECK_TRUE(data3.link_fwd::is_linked()); queue.pop(); - CHECK_TRUE(data1.link_fwd::etl_next == ETL_NULLPTR); - CHECK_TRUE(data2.link_fwd::etl_next == ETL_NULLPTR); - CHECK_TRUE(data3.link_fwd::etl_next == ETL_NULLPTR); + CHECK_FALSE(data1.link_fwd::is_linked()); + CHECK_FALSE(data2.link_fwd::is_linked()); + CHECK_FALSE(data3.link_fwd::is_linked()); } //************************************************************************* @@ -337,24 +376,24 @@ namespace queue.push(data1); queue.push(data2); queue.push(data3); - CHECK_TRUE(data1.link_bdir::etl_next != ETL_NULLPTR); - CHECK_TRUE(data2.link_bdir::etl_next != ETL_NULLPTR); - CHECK_TRUE(data3.link_bdir::etl_next == ETL_NULLPTR); + CHECK_TRUE(data1.link_bdir::is_linked()); + CHECK_TRUE(data2.link_bdir::is_linked()); + CHECK_TRUE(data3.link_bdir::is_linked()); queue.pop(); - CHECK_TRUE(data1.link_bdir::etl_next == ETL_NULLPTR); - CHECK_TRUE(data2.link_bdir::etl_next != ETL_NULLPTR); - CHECK_TRUE(data3.link_bdir::etl_next == ETL_NULLPTR); + CHECK_FALSE(data1.link_bdir::is_linked()); + CHECK_TRUE(data2.link_bdir::is_linked()); + CHECK_TRUE(data3.link_bdir::is_linked()); queue.pop(); - CHECK_TRUE(data1.link_bdir::etl_next == ETL_NULLPTR); - CHECK_TRUE(data2.link_bdir::etl_next == ETL_NULLPTR); - CHECK_TRUE(data3.link_bdir::etl_next == ETL_NULLPTR); + CHECK_FALSE(data1.link_bdir::is_linked()); + CHECK_FALSE(data2.link_bdir::is_linked()); + CHECK_TRUE(data3.link_bdir::is_linked()); queue.pop(); - CHECK_TRUE(data1.link_bdir::etl_next == ETL_NULLPTR); - CHECK_TRUE(data2.link_bdir::etl_next == ETL_NULLPTR); - CHECK_TRUE(data3.link_bdir::etl_next == ETL_NULLPTR); + CHECK_FALSE(data1.link_bdir::is_linked()); + CHECK_FALSE(data2.link_bdir::is_linked()); + CHECK_FALSE(data3.link_bdir::is_linked()); } //************************************************************************* diff --git a/test/test_intrusive_stack.cpp b/test/test_intrusive_stack.cpp index f3f796e1..282d887a 100644 --- a/test/test_intrusive_stack.cpp +++ b/test/test_intrusive_stack.cpp @@ -138,10 +138,30 @@ namespace stackC.push(data2); stackD.clear(); + + CHECK_TRUE(stackD.empty()); + CHECK_FALSE(stackC.empty()); + + CHECK_FALSE(etl::is_linked(data1)); + CHECK_FALSE(etl::is_linked(data2)); + CHECK_FALSE(etl::is_linked(data3)); + + CHECK_TRUE(etl::is_linked(data1)); + CHECK_TRUE(etl::is_linked(data2)); + CHECK_FALSE(etl::is_linked(data3)); + stackC.clear(); - CHECK(stackD.empty()); - CHECK(stackC.empty()); + CHECK_FALSE(etl::is_linked(data1)); + CHECK_FALSE(etl::is_linked(data2)); + CHECK_FALSE(etl::is_linked(data3)); + + CHECK_FALSE(etl::is_linked(data1)); + CHECK_FALSE(etl::is_linked(data2)); + CHECK_FALSE(etl::is_linked(data3)); + + CHECK_TRUE(stackD.empty()); + CHECK_TRUE(stackC.empty()); } //************************************************************************* diff --git a/test/vs2022/etl.sln b/test/vs2022/etl.sln index c93da38d..cc4ecaab 100644 --- a/test/vs2022/etl.sln +++ b/test/vs2022/etl.sln @@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "etl", "etl.vcxproj", "{C21D EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug MSVC C++ 20 - No Tests|Win32 = Debug MSVC C++ 20 - No Tests|Win32 + Debug MSVC C++ 20 - No Tests|x64 = Debug MSVC C++ 20 - No Tests|x64 Debug MSVC C++14 - No STL|Win32 = Debug MSVC C++14 - No STL|Win32 Debug MSVC C++14 - No STL|x64 = Debug MSVC C++14 - No STL|x64 Debug MSVC C++14|Win32 = Debug MSVC C++14|Win32 @@ -25,6 +27,10 @@ Global Release MSVC C++20 - Optimised O2|x64 = Release MSVC C++20 - Optimised O2|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++ 20 - No Tests|Win32.ActiveCfg = Debug MSVC C++ 20 - No Tests|Win32 + {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++ 20 - No Tests|Win32.Build.0 = Debug MSVC C++ 20 - No Tests|Win32 + {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++ 20 - No Tests|x64.ActiveCfg = Debug MSVC C++ 20 - No Tests|x64 + {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++ 20 - No Tests|x64.Build.0 = Debug MSVC C++ 20 - No Tests|x64 {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14 - No STL|Win32.ActiveCfg = Debug MSVC C++14 - No STL|Win32 {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14 - No STL|Win32.Build.0 = Debug MSVC C++14 - No STL|Win32 {C21DF78C-D8E0-46AB-9D6F-D38A3C1CB0FB}.Debug MSVC C++14 - No STL|x64.ActiveCfg = Debug MSVC C++14 - No STL|x64 diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index d3ce830a..df071c55 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -1,6 +1,14 @@  + + Debug MSVC C++ 20 - No Tests + Win32 + + + Debug MSVC C++ 20 - No Tests + x64 + Debug MSVC C++14 - No STL Win32 @@ -95,6 +103,13 @@ Unicode false + + Application + true + v143 + Unicode + false + Application true @@ -300,6 +315,12 @@ v143 Unicode + + Application + true + v143 + Unicode + Application true @@ -524,6 +545,9 @@ + + + @@ -617,6 +641,9 @@ + + + @@ -735,6 +762,11 @@ true $(Configuration)\ + + false + true + $(Configuration)\ + false true @@ -893,6 +925,10 @@ true true + + true + true + true true @@ -1107,6 +1143,31 @@ "$(OutDir)\etl.exe" + + + + + Level2 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ../../../unittest-cpp/;../../include;../../test + + + true + stdcpp20 + ProgramDatabase + /Zc:__cplusplus %(AdditionalOptions) + true + + + Console + true + + + + + + @@ -1865,6 +1926,27 @@ $(OutDir)\etl.exe + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + ../../unittest-cpp/UnitTest++/;../../include/etl;../../test + + + false + stdcpp14 + + + Console + true + + + $(OutDir)\etl.exe + + @@ -2921,6 +3003,7 @@ true true true + true true true true @@ -2954,6 +3037,7 @@ true true true + true true true true @@ -2987,6 +3071,7 @@ true true true + true true true true @@ -3020,6 +3105,7 @@ true true true + true true true true @@ -3097,6 +3183,7 @@ true true true + true true true true @@ -3130,6 +3217,7 @@ true true true + true true true true @@ -3163,6 +3251,7 @@ true true true + true true true true @@ -3196,6 +3285,7 @@ true true true + true true true true @@ -3232,6 +3322,7 @@ true true true + true true true true @@ -3281,6 +3372,7 @@ true true true + true true true true @@ -3319,6 +3411,7 @@ true true true + true true true true @@ -3357,6 +3450,7 @@ true true true + true true true true @@ -3395,6 +3489,7 @@ true true true + true true true true @@ -3433,6 +3528,7 @@ true true true + true true true true @@ -3471,6 +3567,7 @@ true true true + true true true true @@ -3509,6 +3606,7 @@ true true true + true true true true @@ -3547,6 +3645,7 @@ true true true + true true true true @@ -3585,6 +3684,7 @@ true true true + true true true true @@ -3623,6 +3723,7 @@ true true true + true true true true @@ -3645,6 +3746,7 @@ true true true + true true true true @@ -3683,6 +3785,7 @@ true true true + true true true true @@ -3732,6 +3835,7 @@ true true true + true true true true @@ -3757,6 +3861,7 @@ true true true + true true true true @@ -3803,6 +3908,7 @@ true true true + true true true true @@ -3841,6 +3947,7 @@ true true true + true true true true @@ -3879,6 +3986,7 @@ true true true + true true true true @@ -3917,6 +4025,7 @@ true true true + true true true true @@ -3939,6 +4048,7 @@ true true true + true true true true @@ -3973,6 +4083,7 @@ true true true + true true true true @@ -4023,6 +4134,7 @@ true true true + true true true true @@ -4061,6 +4173,7 @@ true true true + true true true true @@ -4099,6 +4212,7 @@ true true true + true true true true @@ -4121,6 +4235,7 @@ true true true + true true true true @@ -4155,6 +4270,7 @@ true true true + true true true true @@ -4189,6 +4305,7 @@ true true true + true true true true @@ -4239,6 +4356,7 @@ true true true + true true true true @@ -4277,6 +4395,7 @@ true true true + true true true true @@ -4315,6 +4434,7 @@ true true true + true true true true @@ -4337,6 +4457,7 @@ true true true + true true true true @@ -4386,6 +4507,7 @@ true true true + true true true true @@ -4424,6 +4546,7 @@ true true true + true true true true @@ -4462,6 +4585,7 @@ true true true + true true true true @@ -4500,6 +4624,7 @@ true true true + true true true true @@ -4538,6 +4663,7 @@ true true true + true true true true @@ -4576,6 +4702,7 @@ true true true + true true true true @@ -4614,6 +4741,7 @@ true true true + true true true true @@ -4652,6 +4780,7 @@ true true true + true true true true @@ -4690,6 +4819,7 @@ true true true + true true true true @@ -4728,6 +4858,7 @@ true true true + true true true true @@ -4766,6 +4897,7 @@ true true true + true true true true @@ -4804,6 +4936,7 @@ true true true + true true true true @@ -4842,6 +4975,7 @@ true true true + true true true true @@ -4880,6 +5014,7 @@ true true true + true true true true @@ -4918,6 +5053,7 @@ true true true + true true true true @@ -4956,6 +5092,7 @@ true true true + true true true true @@ -4994,6 +5131,7 @@ true true true + true true true true @@ -5032,6 +5170,7 @@ true true true + true true true true @@ -5070,6 +5209,7 @@ true true true + true true true true @@ -5108,6 +5248,7 @@ true true true + true true true true @@ -5130,6 +5271,7 @@ true true true + true true true true @@ -5178,6 +5320,7 @@ true true true + true true true true @@ -5216,6 +5359,7 @@ true true true + true true true true @@ -5254,6 +5398,7 @@ true true true + true true true true @@ -5292,6 +5437,7 @@ true true true + true true true true @@ -5330,6 +5476,7 @@ true true true + true true true true @@ -5368,6 +5515,7 @@ true true true + true true true true @@ -5406,6 +5554,7 @@ true true true + true true true true @@ -5444,6 +5593,7 @@ true true true + true true true true @@ -5482,6 +5632,7 @@ true true true + true true true true @@ -5520,6 +5671,7 @@ true true true + true true true true @@ -5558,6 +5710,7 @@ true true true + true true true true @@ -5596,6 +5749,7 @@ true true true + true true true true @@ -5634,6 +5788,7 @@ true true true + true true true true @@ -5672,6 +5827,7 @@ true true true + true true true true @@ -5710,6 +5866,7 @@ true true true + true true true true @@ -5748,6 +5905,7 @@ true true true + true true true true @@ -5786,6 +5944,7 @@ true true true + true true true true @@ -5824,6 +5983,7 @@ true true true + true true true true @@ -5862,6 +6022,7 @@ true true true + true true true true @@ -5900,6 +6061,7 @@ true true true + true true true true @@ -5938,6 +6100,7 @@ true true true + true true true true @@ -5976,6 +6139,7 @@ true true true + true true true true @@ -6014,6 +6178,7 @@ true true true + true true true true @@ -6052,6 +6217,7 @@ true true true + true true true true @@ -6090,6 +6256,7 @@ true true true + true true true true @@ -6128,6 +6295,7 @@ true true true + true true true true @@ -6166,6 +6334,7 @@ true true true + true true true true @@ -6204,6 +6373,7 @@ true true true + true true true true @@ -6242,6 +6412,7 @@ true true true + true true true true @@ -6280,6 +6451,7 @@ true true true + true true true true @@ -6318,6 +6490,7 @@ true true true + true true true true @@ -6340,6 +6513,7 @@ true true true + true true true true @@ -6372,6 +6546,7 @@ true true true + true true true true @@ -6405,6 +6580,7 @@ true true true + true true true true @@ -6454,6 +6630,7 @@ true true true + true true true true @@ -6492,6 +6669,7 @@ true true true + true true true true @@ -6530,6 +6708,7 @@ true true true + true true true true @@ -6568,6 +6747,7 @@ true true true + true true true true @@ -6606,6 +6786,7 @@ true true true + true true true true @@ -6628,6 +6809,7 @@ true true true + true true true true @@ -6659,6 +6841,7 @@ true true true + true true true true @@ -6708,6 +6891,7 @@ true true true + true true true true @@ -6746,6 +6930,7 @@ true true true + true true true true @@ -6784,6 +6969,7 @@ true true true + true true true true @@ -6822,6 +7008,7 @@ true true true + true true true true @@ -6860,6 +7047,7 @@ true true true + true true true true @@ -6898,6 +7086,7 @@ true true true + true true true true @@ -6936,6 +7125,7 @@ true true true + true true true true @@ -6974,6 +7164,7 @@ true true true + true true true true @@ -7012,6 +7203,7 @@ true true true + true true true true @@ -7050,6 +7242,7 @@ true true true + true true true true @@ -7088,6 +7281,7 @@ true true true + true true true true @@ -7126,6 +7320,7 @@ true true true + true true true true @@ -7164,6 +7359,7 @@ true true true + true true true true @@ -7202,6 +7398,7 @@ true true true + true true true true @@ -7240,6 +7437,7 @@ true true true + true true true true @@ -7278,6 +7476,7 @@ true true true + true true true true @@ -7316,6 +7515,7 @@ true true true + true true true true @@ -7354,6 +7554,7 @@ true true true + true true true true @@ -7392,6 +7593,7 @@ true true true + true true true true @@ -7430,6 +7632,7 @@ true true true + true true true true @@ -7468,6 +7671,7 @@ true true true + true true true true @@ -7506,6 +7710,7 @@ true true true + true true true true @@ -7544,6 +7749,7 @@ true true true + true true true true @@ -7582,6 +7788,7 @@ true true true + true true true true @@ -7620,6 +7827,7 @@ true true true + true true true true @@ -7658,6 +7866,7 @@ true true true + true true true true @@ -7696,6 +7905,7 @@ true true true + true true true true @@ -7734,6 +7944,7 @@ true true true + true true true true @@ -7772,6 +7983,7 @@ true true true + true true true true @@ -7810,6 +8022,7 @@ true true true + true true true true @@ -7832,6 +8045,7 @@ true true true + true true true true @@ -7882,6 +8096,7 @@ true true true + true true true true @@ -7920,6 +8135,7 @@ true true true + true true true true @@ -7958,6 +8174,7 @@ true true true + true true true true @@ -7996,6 +8213,7 @@ true true true + true true true true @@ -8034,6 +8252,7 @@ true true true + true true true true @@ -8072,6 +8291,7 @@ true true true + true true true true @@ -8110,6 +8330,7 @@ true true true + true true true true @@ -8148,6 +8369,7 @@ true true true + true true true true @@ -8186,6 +8408,7 @@ true true true + true true true true @@ -8224,6 +8447,7 @@ true true true + true true true true @@ -8262,6 +8486,7 @@ true true true + true true true true @@ -8300,6 +8525,7 @@ true true true + true true true true @@ -8338,6 +8564,7 @@ true true true + true true true true @@ -8376,6 +8603,7 @@ true true true + true true true true @@ -8414,6 +8642,7 @@ true true true + true true true true @@ -8452,6 +8681,7 @@ true true true + true true true true @@ -8490,6 +8720,7 @@ true true true + true true true true @@ -8528,6 +8759,7 @@ true true true + true true true true @@ -8566,6 +8798,7 @@ true true true + true true true true @@ -8604,6 +8837,7 @@ true true true + true true true true @@ -8642,6 +8876,7 @@ true true true + true true true true @@ -8680,6 +8915,7 @@ true true true + true true true true @@ -8718,6 +8954,7 @@ true true true + true true true true @@ -8756,6 +8993,7 @@ true true true + true true true true @@ -8794,6 +9032,7 @@ true true true + true true true true @@ -8832,6 +9071,7 @@ true true true + true true true true @@ -8870,6 +9110,7 @@ true true true + true true true true @@ -8908,6 +9149,7 @@ true true true + true true true true @@ -8946,6 +9188,7 @@ true true true + true true true true @@ -8984,6 +9227,7 @@ true true true + true true true true @@ -9022,6 +9266,7 @@ true true true + true true true true @@ -9044,6 +9289,7 @@ true true true + true true true true @@ -9078,6 +9324,7 @@ true true true + true true true true @@ -9112,6 +9359,7 @@ true true true + true true true true @@ -9162,6 +9410,7 @@ true true true + true true true true @@ -9200,6 +9449,7 @@ true true true + true true true true @@ -9238,6 +9488,7 @@ true true true + true true true true @@ -9276,6 +9527,7 @@ true true true + true true true true @@ -9314,6 +9566,7 @@ true true true + true true true true @@ -9336,6 +9589,7 @@ true true true + true true true true @@ -9370,6 +9624,7 @@ true true true + true true true true @@ -9420,6 +9675,7 @@ true true true + true true true true @@ -9458,6 +9714,7 @@ true true true + true true true true @@ -9496,6 +9753,7 @@ true true true + true true true true @@ -9518,6 +9776,7 @@ true true true + true true true true @@ -9568,6 +9827,7 @@ true true true + true true true true @@ -9606,6 +9866,7 @@ true true true + true true true true @@ -9644,6 +9905,7 @@ true true true + true true true true @@ -9682,6 +9944,7 @@ true true true + true true true true @@ -9720,6 +9983,7 @@ true true true + true true true true @@ -9758,6 +10022,7 @@ true true true + true true true true @@ -9796,6 +10061,7 @@ true true true + true true true true @@ -9834,6 +10100,7 @@ true true true + true true true true @@ -9872,6 +10139,7 @@ true true true + true true true true @@ -9910,6 +10178,7 @@ true true true + true true true true @@ -9948,6 +10217,7 @@ true true true + true true true true @@ -9986,6 +10256,7 @@ true true true + true true true true @@ -10024,6 +10295,7 @@ true true true + true true true true @@ -10062,6 +10334,7 @@ true true true + true true true true @@ -10100,6 +10373,7 @@ true true true + true true true true @@ -10138,6 +10412,7 @@ true true true + true true true true @@ -10176,6 +10451,7 @@ true true true + true true true true @@ -10214,6 +10490,7 @@ true true true + true true true true @@ -10252,6 +10529,7 @@ true true true + true true true true @@ -10290,6 +10568,7 @@ true true true + true true true true @@ -10328,6 +10607,7 @@ true true true + true true true true @@ -10366,6 +10646,7 @@ true true true + true true true true @@ -10404,6 +10685,7 @@ true true true + true true true true @@ -10442,6 +10724,7 @@ true true true + true true true true @@ -10480,6 +10763,7 @@ true true true + true true true true @@ -10518,6 +10802,7 @@ true true true + true true true true @@ -10556,6 +10841,7 @@ true true true + true true true true @@ -10594,6 +10880,7 @@ true true true + true true true true @@ -10632,6 +10919,7 @@ true true true + true true true true @@ -10670,6 +10958,7 @@ true true true + true true true true @@ -10708,6 +10997,7 @@ true true true + true true true true @@ -10746,6 +11036,7 @@ true true true + true true true true @@ -10784,6 +11075,7 @@ true true true + true true true true @@ -10822,6 +11114,7 @@ true true true + true true true true @@ -10860,6 +11153,7 @@ true true true + true true true true @@ -10898,6 +11192,7 @@ true true true + true true true true @@ -10936,6 +11231,7 @@ true true true + true true true true @@ -10974,6 +11270,7 @@ true true true + true true true true @@ -11012,6 +11309,7 @@ true true true + true true true true @@ -11034,6 +11332,7 @@ true true true + true true true true @@ -11084,6 +11383,7 @@ true true true + true true true true @@ -11122,6 +11422,7 @@ true true true + true true true true @@ -11160,6 +11461,7 @@ true true true + true true true true @@ -11198,6 +11500,7 @@ true true true + true true true true @@ -11236,6 +11539,7 @@ true true true + true true true true @@ -11274,6 +11578,7 @@ true true true + true true true true @@ -11312,6 +11617,7 @@ true true true + true true true true @@ -11350,6 +11656,7 @@ true true true + true true true true @@ -11388,6 +11695,7 @@ true true true + true true true true @@ -11426,6 +11734,7 @@ true true true + true true true true @@ -11464,6 +11773,7 @@ true true true + true true true true @@ -11502,6 +11812,7 @@ true true true + true true true true @@ -11540,6 +11851,7 @@ true true true + true true true true @@ -11578,6 +11890,7 @@ true true true + true true true true @@ -11616,6 +11929,7 @@ true true true + true true true true @@ -11638,6 +11952,7 @@ true true true + true true true true @@ -11687,6 +12002,7 @@ true true true + true true true true @@ -11725,6 +12041,7 @@ true true true + true true true true @@ -11763,6 +12080,7 @@ true true true + true true true true @@ -11801,6 +12119,7 @@ true true true + true true true true @@ -11839,6 +12158,7 @@ true true true + true true true true @@ -11877,6 +12197,7 @@ true true true + true true true true @@ -11915,6 +12236,7 @@ true true true + true true true true @@ -11953,6 +12275,7 @@ true true true + true true true true @@ -11991,6 +12314,7 @@ true true true + true true true true @@ -12029,6 +12353,7 @@ true true true + true true true true @@ -12067,6 +12392,7 @@ true true true + true true true true @@ -12105,6 +12431,7 @@ true true true + true true true true @@ -12143,6 +12470,7 @@ true true true + true true true true @@ -12181,6 +12509,7 @@ true true true + true true true true @@ -12204,6 +12533,7 @@ true true true + true true true true @@ -12253,6 +12583,7 @@ true true true + true true true true @@ -12291,6 +12622,7 @@ true true true + true true true true @@ -12329,6 +12661,7 @@ true true true + true true true true @@ -12367,6 +12700,7 @@ true true true + true true true true @@ -12405,6 +12739,7 @@ true true true + true true true true @@ -12443,6 +12778,7 @@ true true true + true true true true @@ -12481,6 +12817,7 @@ true true true + true true true true @@ -12519,6 +12856,7 @@ true true true + true true true true @@ -12557,6 +12895,7 @@ true true true + true true true true @@ -12595,6 +12934,7 @@ true true true + true true true true @@ -12633,6 +12973,7 @@ true true true + true true true true @@ -12671,6 +13012,7 @@ true true true + true true true true @@ -12709,6 +13051,7 @@ true true true + true true true true @@ -12747,6 +13090,7 @@ true true true + true true true true @@ -12785,6 +13129,7 @@ true true true + true true true true @@ -12823,6 +13168,7 @@ true true true + true true true true @@ -12861,6 +13207,7 @@ true true true + true true true true @@ -12899,6 +13246,7 @@ true true true + true true true true @@ -13055,6 +13403,7 @@ false false false + false false false false @@ -13090,6 +13439,7 @@ false false false + false false false false @@ -13144,6 +13494,7 @@ false false false + false false false false @@ -13179,6 +13530,7 @@ false false false + false false false false @@ -13228,6 +13580,7 @@ false false false + false false false false @@ -13263,6 +13616,7 @@ false false false + false false false false @@ -13302,6 +13656,7 @@ false false false + false false false false @@ -13337,6 +13692,7 @@ false false false + false false false false @@ -13376,6 +13732,7 @@ false false false + false false false false @@ -13411,6 +13768,7 @@ false false false + false false false false @@ -13450,6 +13808,7 @@ false false false + false false false false @@ -13485,6 +13844,7 @@ false false false + false false false false @@ -13529,6 +13889,7 @@ false false false + false false false false @@ -13564,6 +13925,7 @@ false false false + false false false false @@ -13607,6 +13969,7 @@ false false false + false false false false @@ -13642,6 +14005,7 @@ false false false + false false false false @@ -13694,6 +14058,7 @@ false false false + false false false false @@ -13729,6 +14094,7 @@ false false false + false false false false @@ -13946,6 +14312,7 @@ true true true + true true true true @@ -13979,6 +14346,7 @@ true true true + true true true true @@ -14012,6 +14380,7 @@ true true true + true true true true @@ -14045,6 +14414,7 @@ true true true + true true true true