From 940b5eda3ba0c9033a541db21b3647b9b927d9c3 Mon Sep 17 00:00:00 2001 From: jwellbelove Date: Tue, 11 Nov 2014 15:23:43 +0000 Subject: [PATCH] Optimisations & others Optimisations & use more iterators in implementation --- ilist.h | 530 +++++++++++++++++++++++++++++--------------------------- list.h | 16 +- 2 files changed, 285 insertions(+), 261 deletions(-) diff --git a/ilist.h b/ilist.h index 8549236f..9ebff971 100644 --- a/ilist.h +++ b/ilist.h @@ -52,38 +52,48 @@ namespace etl class ilist : public list_base { protected: - + //************************************************************************* /// The node element in the list. //************************************************************************* - struct Data_Node; - struct Node { + //*********************************************************************** + /// Constructor + //*********************************************************************** Node() : previous(nullptr), next(nullptr) { } - void mark_as_free() + //*********************************************************************** + /// Marks the node as free. + //*********************************************************************** + inline void mark_as_free() { previous = nullptr; next = nullptr; } - bool is_free() const + //*********************************************************************** + /// Checks if the node is free. + //*********************************************************************** + inline bool is_free() const { return next == nullptr; } - void reverse() + //*********************************************************************** + /// Reverses the previous & next pointers. + //*********************************************************************** + inline void reverse() { std::swap(previous, next); } - Data_Node* previous; - Data_Node* next; + Node* previous; + Node* next; }; //************************************************************************* @@ -94,13 +104,45 @@ namespace etl T value; }; - protected: - - Node terminal_node; ///< The node that acts as the list start and end. + /// The node that acts as the list start and end. + Node terminal_node; private: - Data_Node* node_pool; ///< The pool of data nodes used in the list. + /// The pool of data nodes used in the list. + Data_Node* node_pool; + + //************************************************************************* + /// Downcast a Node* to a Data_Node* + //************************************************************************* + inline static Data_Node* data_cast(Node* p_node) + { + return static_cast(p_node); + } + + //************************************************************************* + /// Downcast a Node& to a Data_Node& + //************************************************************************* + inline static Data_Node& data_cast(Node& node) + { + return static_cast(node); + } + + //************************************************************************* + /// Downcast a const Node* to a const Data_Node* + //************************************************************************* + inline static const Data_Node* data_cast(const Node* p_node) + { + return static_cast(p_node); + } + + //************************************************************************* + /// Downcast a const Node& to a const Data_Node& + //************************************************************************* + inline static const Data_Node& data_cast(const Node& node) + { + return static_cast(node); + } public: @@ -120,96 +162,96 @@ namespace etl friend class ilist; - iterator() + inline iterator() : p_node(nullptr) { } - iterator(Data_Node& node) + inline iterator(Node& node) : p_node(&node) { } - iterator(const iterator& other) + inline iterator(const iterator& other) : p_node(other.p_node) { } - iterator& operator ++() + inline iterator& operator ++() { p_node = p_node->next; return *this; } - iterator operator ++(int) + inline iterator operator ++(int) { iterator temp(*this); p_node = p_node->next; return temp; } - iterator& operator --() + inline iterator& operator --() { p_node = p_node->previous; return *this; } - iterator operator --(int) + inline iterator operator --(int) { iterator temp(*this); p_node = p_node->previous; return temp; } - iterator operator =(const iterator& other) + inline iterator operator =(const iterator& other) { p_node = other.p_node; return *this; } - reference operator *() + inline reference operator *() + { + return ilist::data_cast(p_node)->value; + } + + inline const_reference operator *() const { return p_node->value; } - const_reference operator *() const + inline pointer operator &() { - return p_node->value; + return &(ilist::data_cast(p_node)->value); } - pointer operator &() + inline const_pointer operator &() const { - return &(p_node->value); + return &(ilist::data_cast(p_node)->value); } - const_pointer operator &() const + inline pointer operator ->() { - return &(p_node->value); + return &(ilist::data_cast(p_node)->value); } - pointer operator ->() + inline const_pointer operator ->() const { - return &(p_node->value); + return &(ilist::data_cast(p_node)->value); } - const_pointer operator ->() const - { - return &(p_node->value); - } - - friend bool operator == (const iterator& lhs, const iterator& rhs) + inline friend bool operator == (const iterator& lhs, const iterator& rhs) { return lhs.p_node == rhs.p_node; } - friend bool operator != (const iterator& lhs, const iterator& rhs) + inline friend bool operator != (const iterator& lhs, const iterator& rhs) { return !(lhs == rhs); } private: - Data_Node* p_node; + Node* p_node; }; //************************************************************************* @@ -221,96 +263,96 @@ namespace etl friend class ilist; - const_iterator() + inline const_iterator() : p_node(nullptr) { } - const_iterator(Data_Node& node) + inline const_iterator(Node& node) : p_node(&node) { } - const_iterator(const Data_Node& node) + inline const_iterator(const Node& node) : p_node(&node) { } - const_iterator(const typename ilist::iterator& other) + inline const_iterator(const typename ilist::iterator& other) : p_node(other.p_node) { } - const_iterator(const const_iterator& other) + inline const_iterator(const const_iterator& other) : p_node(other.p_node) { } - const_iterator& operator ++() + inline const_iterator& operator ++() { p_node = p_node->next; return *this; } - const_iterator operator ++(int) + inline const_iterator operator ++(int) { const_iterator temp(*this); p_node = p_node->next; return temp; } - const_iterator& operator --() + inline const_iterator& operator --() { p_node = p_node->previous; return *this; } - const_iterator operator --(int) + inline const_iterator operator --(int) { const_iterator temp(*this); p_node = p_node->previous; return temp; } - const_iterator operator =(const const_iterator& other) + inline const_iterator operator =(const const_iterator& other) { p_node = other.p_node; return *this; } - const_reference operator *() const + inline const_reference operator *() const { - return p_node->value; + return ilist::data_cast(p_node)->value; } - const_pointer operator &() const + inline const_pointer operator &() const { - return p_node->value; + return ilist::data_cast(p_node)->value; } - Data_Node* operator ->() + inline Data_Node* operator ->() { return p_node; } - const Data_Node* operator ->() const + inline const Data_Node* operator ->() const { return p_node; } - friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) + inline friend bool operator == (const const_iterator& lhs, const const_iterator& rhs) { return lhs.p_node == rhs.p_node; } - friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) + inline friend bool operator != (const const_iterator& lhs, const const_iterator& rhs) { return !(lhs == rhs); } private: - const Data_Node* p_node; + const Node* p_node; }; typedef typename std::iterator_traits::difference_type difference_type; @@ -321,7 +363,7 @@ namespace etl //************************************************************************* /// Gets the beginning of the list. //************************************************************************* - iterator begin() + inline iterator begin() { return iterator(get_head()); } @@ -329,7 +371,7 @@ namespace etl //************************************************************************* /// Gets the beginning of the list. //************************************************************************* - const_iterator begin() const + inline const_iterator begin() const { return const_iterator(get_head()); } @@ -337,7 +379,7 @@ namespace etl //************************************************************************* /// Gets the beginning of the list. //************************************************************************* - const_iterator cbegin() const + inline const_iterator cbegin() const { return const_iterator(get_head()); } @@ -345,15 +387,15 @@ namespace etl //************************************************************************* /// Gets the reverse beginning of the list. //************************************************************************* - reverse_iterator rbegin() + inline reverse_iterator rbegin() { - return reverse_iterator(static_cast(terminal_node)); + return reverse_iterator(terminal_node); } //************************************************************************* /// Gets the reverse beginning of the list. //************************************************************************* - const_reverse_iterator rbegin() const + inline const_reverse_iterator rbegin() const { return const_reverse_iterator(static_cast(terminal_node)); } @@ -361,7 +403,7 @@ namespace etl //************************************************************************* /// Gets the reverse beginning of the list. //************************************************************************* - const_reverse_iterator crbegin() const + inline const_reverse_iterator crbegin() const { return const_reverse_iterator(static_cast(terminal_node)); } @@ -369,15 +411,15 @@ namespace etl //************************************************************************* /// Gets the end of the list. //************************************************************************* - iterator end() + inline iterator end() { - return iterator(static_cast(terminal_node)); + return iterator(terminal_node); } //************************************************************************* /// Gets the end of the list. //************************************************************************* - const_iterator end() const + inline const_iterator end() const { return const_iterator(static_cast(terminal_node)); } @@ -385,7 +427,7 @@ namespace etl //************************************************************************* /// Gets the end of the list. //************************************************************************* - const_iterator cend() const + inline const_iterator cend() const { return const_iterator(static_cast(terminal_node)); } @@ -393,7 +435,7 @@ namespace etl //************************************************************************* /// Gets the reverse end of the list. //************************************************************************* - reverse_iterator rend() + inline reverse_iterator rend() { return reverse_iterator(get_head()); } @@ -401,7 +443,7 @@ namespace etl //************************************************************************* /// Gets the reverse end of the list. //************************************************************************* - const_reverse_iterator rend() const + inline const_reverse_iterator rend() const { return const_reverse_iterator(get_head()); } @@ -409,7 +451,7 @@ namespace etl //************************************************************************* /// Gets the reverse end of the list. //************************************************************************* - const_reverse_iterator crend() const + inline const_reverse_iterator crend() const { return const_reverse_iterator(get_head()); } @@ -417,7 +459,7 @@ namespace etl //************************************************************************* /// Assignment operator. //************************************************************************* - ilist& operator = (const ilist& rhs) + inline ilist& operator = (const ilist& rhs) { assign(rhs.cbegin(), rhs.cend()); @@ -427,7 +469,7 @@ namespace etl //************************************************************************* /// Clears the list. //************************************************************************* - void clear() + inline void clear() { initialise(); } @@ -435,33 +477,33 @@ namespace etl //************************************************************************* /// Gets a reference to the first element. //************************************************************************* - reference front() + inline reference front() { - return get_head().value; + return data_cast(get_head()).value; } //************************************************************************* /// Gets a const reference to the first element. //************************************************************************* - const_reference front() const + inline const_reference front() const { - return get_head().value; + return data_cast(get_head()).value; } //************************************************************************* /// Gets a reference to the last element. //************************************************************************* - reference back() + inline reference back() { - return get_tail().value; + return data_cast(get_tail()).value; } //************************************************************************* /// Gets a reference to the last element. //************************************************************************* - const_reference back() const + inline const_reference back() const { - return get_tail().value; + return data_cast(get_tail()).value; } //************************************************************************* @@ -472,46 +514,36 @@ namespace etl template void assign(TIterator first, TIterator last) { -#ifdef _DEBUG - if (std::distance(first, last) < 0) - { -#ifdef ETL_USE_EXCEPTIONS - throw list_iterator(); -#endif - } - else -#endif - { - // Reset the links. - join(terminal_node, terminal_node); + // Reset the links. + join(terminal_node, terminal_node); + count = 0; - size_t i = 0; - - // Add all of the elements. - while (first != last) + // Add all of the elements. + while (first != last) + { + if (!full()) { -#ifdef ETL_USE_EXCEPTIONS - if (i == MAX_SIZE) - { - throw list_full(); - } -#endif - Data_Node& data_node = node_pool[i]; - data_node.value = *first++; - join(*terminal_node.previous, data_node); + Data_Node& data_node = node_pool[count]; + data_node.value = *first; + join(get_tail(), data_node); join(data_node, terminal_node); - ++i; } - - next_free = i; - count = i; - - // Clear the remaining elements in the node pool. - while (i < MAX_SIZE) +#ifdef ETL_USE_EXCEPTIONS + else { - node_pool[i].mark_as_free(); - ++i; + throw list_full(); } +#endif + ++first; + ++count; + } + + next_free = count; + + // Clear the remaining elements in the node pool. + for (size_t i = count; i < MAX_SIZE; ++i) + { + node_pool[i].mark_as_free(); } } @@ -520,39 +552,37 @@ namespace etl //************************************************************************* void assign(size_t n, const_reference value) { - if (n <= MAX_SIZE) + // Reset the links. + join(terminal_node, terminal_node); + count = 0; + + // Add all of the elements. + while (count < n) { - // Reset the links. - join(terminal_node, terminal_node); - - size_t i = 0; - - // Add all of the elements. - while (i < n) + if (!full()) { - Data_Node& data_node = node_pool[i]; + Data_Node& data_node = node_pool[count]; data_node.value = value; join(*terminal_node.previous, data_node); join(data_node, terminal_node); - ++i; } - - next_free = i; - count = i; - - // Clear the remaining elements in the node pool. - while (i < MAX_SIZE) - { - node_pool[i].mark_as_free(); - ++i; - } - } #ifdef ETL_USE_EXCEPTIONS - else - { - throw list_full(); - } + else + { + throw list_full(); + } #endif + + ++count; + } + + next_free = count; + + // Clear the remaining elements in the node pool. + for (size_t i = count; i < MAX_SIZE; ++i) + { + node_pool[i].mark_as_free(); + } } //************************************************************************* @@ -563,7 +593,6 @@ namespace etl if (!full()) { Data_Node& data_node = node_pool[next_free]; - insert_node(get_head(), data_node); } #ifdef ETL_USE_EXCEPTIONS @@ -583,7 +612,6 @@ namespace etl { Data_Node& data_node = node_pool[next_free]; data_node.value = value; - insert_node(get_head(), data_node); } #ifdef ETL_USE_EXCEPTIONS @@ -602,7 +630,6 @@ namespace etl if (!full()) { Data_Node& data_node = node_pool[next_free]; - insert_node(terminal_node, data_node); } #if ETL_USE_EXCEPTIONS @@ -622,7 +649,6 @@ namespace etl { Data_Node& data_node = node_pool[next_free]; data_node.value = value; - insert_node(terminal_node, data_node); } #if ETL_USE_EXCEPTIONS @@ -668,26 +694,27 @@ namespace etl //************************************************************************* void resize(size_t n, T value) { - if (n <= MAX_SIZE) + if (n > MAX_SIZE) { - // Reduce if necessary. - while (size() > n) - { - pop_back(); - } - - // Increase if necessary. - while (size() < n) - { - push_back(value); - } - } #if ETL_USE_EXCEPTIONS - else - { throw list_full(); - } +#else + n = MAX_SIZE; #endif + } + + // Smaller? + if (n < size()) + { + iterator i_start = end(); + std::advance(i_start, -difference_type(size() - n)); + erase(i_start, end()); + } + // Larger? + else if (n > size()) + { + insert(end(), n - size(), value); + } } //************************************************************************* @@ -700,15 +727,16 @@ namespace etl return; } - Node* p_current = &get_head(); + iterator i_item = begin(); - for (size_t i = 0; i < size(); ++i) + while (i_item != end()) { - p_current->reverse(); - p_current = p_current->previous; + i_item.p_node->reverse(); + --i_item; // Now we've reversed it, we must decrement it. } - terminal_node.reverse(); + // Terminal node. + i_item.p_node->reverse(); } //************************************************************************* @@ -743,23 +771,22 @@ namespace etl //************************************************************************* void insert(iterator position, size_t n, const value_type& value) { - if (!full()) + for (size_t i = 0; i < n; ++i) { - for (size_t i = 0; !full() && (i < n); ++i) + if (!full()) { - // Set up the next free node. + // Set up the next free node and insert. Data_Node& data_node = node_pool[next_free]; data_node.value = value; - insert_node(*position.p_node, data_node); } - } #if ETL_USE_EXCEPTIONS - else - { - throw list_full(); - } + else + { + throw list_full(); + } #endif + } } //************************************************************************* @@ -768,24 +795,22 @@ namespace etl template void insert(iterator position, TIterator first, TIterator last) { - if ((size() + std::distance(first, last)) <= MAX_SIZE) + while (first != last) { - while (first != last) + if (!full()) { - // Set up the next free node. + // Set up the next free node and insert. Data_Node& data_node = node_pool[next_free]; - data_node.value = *first; - + data_node.value = *first++; insert_node(*position.p_node, data_node); - ++first; } - } #if ETL_USE_EXCEPTIONS - else - { - throw list_full(); - } + else + { + throw list_full(); + } #endif + } } //************************************************************************* @@ -817,7 +842,7 @@ namespace etl while (p_first != p_last) { // Update the position of the earliest free node in the pool. - size_t new_free = std::distance(&node_pool[0], static_cast(p_first)); + size_t new_free = std::distance(&node_pool[0], data_cast(p_first)); next_free = std::min(next_free, new_free); // One less. @@ -835,7 +860,7 @@ namespace etl /// Removes all but the first element from every consecutive group of equal /// elements in the container. //************************************************************************* - void unique() + inline void unique() { unique(std::equal_to()); } @@ -852,17 +877,21 @@ namespace etl return; } - Data_Node* current = get_head().next; + iterator i_item = begin(); + ++i_item; + iterator i_previous = begin(); - while (current != &terminal_node) + while (i_item != end()) { - Data_Node* next = current->next; - if (isEqual(current->previous->value, current->value)) + if (isEqual(*i_previous, *i_item)) { - remove_node(*current); + i_item = erase(i_item); + } + else + { + i_previous = i_item; + ++i_item; } - - current = next; } } @@ -870,7 +899,7 @@ namespace etl /// Sort using in-place merge sort algorithm. /// Uses 'less-than operator as the predicate. //************************************************************************* - void sort() + inline void sort() { sort(std::less()); } @@ -883,11 +912,11 @@ namespace etl template void sort(TCompare compare) { - Data_Node* p_left; - Data_Node* p_right; - Data_Node* p_node; - Data_Node* p_head; - Data_Node* p_tail; + iterator i_left; + iterator i_right; + iterator i_node; + iterator i_head; + iterator i_tail; int list_size = 1; int number_of_merges; int left_size; @@ -895,31 +924,30 @@ namespace etl if (is_trivial_list()) { - return; + return; } while (true) { - p_left = &get_head(); - p_head = &static_cast(terminal_node); - p_tail = &static_cast(terminal_node); + i_left = begin(); + i_head = end(); + i_tail = end(); number_of_merges = 0; // Count the number of merges we do in this pass. - while (p_left != &terminal_node) + while (i_left != end()) { ++number_of_merges; // There exists a merge to be done. - p_right = p_left; + i_right = i_left; left_size = 0; // Step 'list_size' places along from left for (int i = 0; i < list_size; ++i) { ++left_size; + ++i_right; - p_right = p_right->next; - - if (p_right == &terminal_node) + if (i_right == end()) { break; } @@ -929,62 +957,59 @@ namespace etl right_size = list_size; // Now we have two lists. Merge them. - while (left_size > 0 || (right_size > 0 && p_right != &terminal_node)) + while (left_size > 0 || (right_size > 0 && i_right != end())) { // Decide whether the next node of merge comes from left or right. if (left_size == 0) { - // Left is empty. The node must come from right. - p_node = p_right; - p_right = p_right->next; + // Left is empty. The node must come from right. + i_node = i_right++; --right_size; - } - else if (right_size == 0 || p_right == &terminal_node) + } + else if (right_size == 0 || i_right == end()) { - // Right is empty. The node must come from left. - p_node = p_left; - p_left = p_left->next; + // Right is empty. The node must come from left. + i_node = i_left++; --left_size; - } - else if (compare(p_left->value, p_right->value)) + } + else if (compare(*i_left, *i_right)) { - // First node of left is lower or same. The node must come from left. - p_node = p_left; - p_left = p_left->next; + // First node of left is lower or same. The node must come from left. + i_node = i_left++; --left_size; - } + } else { - // First node of right is lower. The node must come from right. - p_node = p_right; - p_right = p_right->next; + // First node of right is lower. The node must come from right. + i_node = i_right; + ++i_right; --right_size; - } + } // Add the next node to the merged head. - if (p_head == &terminal_node) + if (i_head == end()) { - join(*p_head, *p_node); - p_head = p_node; - p_tail = p_node; + join(*i_head.p_node, *i_node.p_node); + i_head = i_node; + i_tail = i_node; } else { - join(*p_tail, *p_node); - p_tail = p_node; + join(*i_tail.p_node, *i_node.p_node); + i_tail = i_node; } - join(*p_tail, terminal_node); + join(*i_tail.p_node, terminal_node); } // Now left has stepped `list_size' places along, and right has too. - p_left = p_right; + i_left = i_right; } // If we have done only one merge, we're finished. if (number_of_merges <= 1) // Allow for number_of_merges == 0, the empty head case { - return; + return; } // Otherwise repeat, merging lists twice the size @@ -1050,16 +1075,16 @@ namespace etl //************************************************************************* /// Join two nodes. //************************************************************************* - void join(Node& left, Node& right) + inline void join(Node& left, Node& right) { - left.next = &static_cast(right); - right.previous = &static_cast(left); + left.next = &right; + right.previous = &left; } //************************************************************************* /// Join two nodes. //************************************************************************* - void join(Data_Node& left, Data_Node& right) + inline void join(Data_Node& left, Data_Node& right) { left.next = &right; right.previous = &left; @@ -1068,7 +1093,7 @@ namespace etl //************************************************************************* /// Is the list a trivial length? //************************************************************************* - bool is_trivial_list() const + inline bool is_trivial_list() const { return (size() < 2); } @@ -1110,10 +1135,10 @@ namespace etl //************************************************************************* /// Remove a node. //************************************************************************* - void remove_node(Data_Node& node) + void remove_node(Node& node) { // Update the position of the next free node in the pool. - size_t new_free = std::distance(&node_pool[0], &node); + size_t new_free = std::distance(&node_pool[0], data_cast(&node)); next_free = std::min(next_free, new_free); // One less. @@ -1127,33 +1152,33 @@ namespace etl //************************************************************************* /// Get the head node. //************************************************************************* - Data_Node& get_head() + inline Node& get_head() { - return static_cast(*terminal_node.next); + return *terminal_node.next; } //************************************************************************* /// Get the head node. //************************************************************************* - const Data_Node& get_head() const + inline const Node& get_head() const { - return static_cast(*terminal_node.next); + return *terminal_node.next; } //************************************************************************* /// Get the tail node. //************************************************************************* - Data_Node& get_tail() + inline Node& get_tail() { - return static_cast(*terminal_node.previous); + return *terminal_node.previous; } //************************************************************************* /// Get the tail node. //************************************************************************* - const Data_Node& get_tail() const + inline const Node& get_tail() const { - return static_cast(*terminal_node.previous); + return *terminal_node.previous; } //************************************************************************* @@ -1183,8 +1208,7 @@ namespace etl template bool operator ==(const etl::ilist& lhs, const etl::ilist& rhs) { - return (lhs.size() == rhs.size()) && - std::equal(lhs.begin(), lhs.end(), rhs.begin()); + return (lhs.size() == rhs.size()) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); } //************************************************************************* diff --git a/list.h b/list.h index d7a51377..8b7194e5 100644 --- a/list.h +++ b/list.h @@ -117,13 +117,13 @@ namespace etl // Re-align the node pointers for this list. if (this->terminal_node.previous != 0) { - size_t index = std::distance(&node_pool[0], this->terminal_node.previous); + size_t index = std::distance(&node_pool[0], static_cast(this->terminal_node.previous)); this->terminal_node.previous = &node_pool[index]; } if (this->terminal_node.next != 0) { - size_t index = std::distance(&node_pool[0], this->terminal_node.next); + size_t index = std::distance(&node_pool[0], static_cast(this->terminal_node.next)); this->terminal_node.next = &node_pool[index]; } @@ -135,10 +135,10 @@ namespace etl { size_t index; - index = std::distance(&node_pool[0], data_node.previous); + index = std::distance(&node_pool[0], static_cast(data_node.previous)); data_node.previous = &other.node_pool[index]; - index = std::distance(&node_pool[0], data_node.next); + index = std::distance(&node_pool[0], static_cast(data_node.next)); data_node.next = &other.node_pool[index]; } } @@ -146,13 +146,13 @@ namespace etl // Re-align the node pointers for the other list. if (other.terminal_node.previous != 0) { - size_t index = std::distance(&other.node_pool[0], other.terminal_node.previous); + size_t index = std::distance(&other.node_pool[0], static_cast(other.terminal_node.previous)); other.terminal_node.previous = &other.node_pool[index]; } if (other.terminal_node.next != 0) { - size_t index = std::distance(&other.node_pool[0], other.terminal_node.next); + size_t index = std::distance(&other.node_pool[0], static_cast(other.terminal_node.next)); other.terminal_node.next = &other.node_pool[index]; } @@ -164,10 +164,10 @@ namespace etl { size_t index; - index = std::distance(&other.node_pool[0], data_node.previous); + index = std::distance(&other.node_pool[0], static_cast(data_node.previous)); data_node.previous = &node_pool[index]; - index = std::distance(&other.node_pool[0], data_node.next); + index = std::distance(&other.node_pool[0], static_cast(data_node.next)); data_node.next = &node_pool[index]; } }