#ifndef SQL_PLIST_H #define SQL_PLIST_H /* Copyright (c) 2009, 2024, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. This program is designed to work with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the separately licensed software that they have either included with the program or referenced in the documentation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "my_inttypes.h" template class I_P_List_iterator; class I_P_List_null_counter; template class I_P_List_no_push_back; /** Intrusive parameterized list. Unlike I_List does not require its elements to be descendant of ilink class and therefore allows them to participate in several such lists simultaneously. Unlike List is doubly-linked list and thus supports efficient deletion of element without iterator. @tparam T Type of elements which will belong to list. @tparam B Class which via its methods specifies which members of T should be used for participating in this list. Here is typical layout of such class: struct B { static inline T **next_ptr(T *el) { return &el->next; } static inline T ***prev_ptr(T *el) { return &el->prev; } }; @tparam C Policy class specifying how counting of elements in the list should be done. Instance of this class is also used as a place where information about number of list elements is stored. @sa I_P_List_null_counter, I_P_List_counter @tparam I Policy class specifying whether I_P_List should support efficient push_back() operation. Instance of this class is used as place where we store information to support this operation. @sa I_P_List_no_push_back, I_P_List_fast_push_back. */ template > class I_P_List : public C, public I { T *m_first; /* Do not prohibit copying of I_P_List object to simplify their usage in backup/restore scenarios. Note that performing any operations on such is a bad idea. */ public: I_P_List() : I(&m_first), m_first(nullptr) {} inline void clear() { m_first = nullptr; C::reset(); I::set_last(&m_first); } inline bool is_empty() const { return (m_first == nullptr); } inline void push_front(T *a) { *B::next_ptr(a) = m_first; if (m_first) *B::prev_ptr(m_first) = B::next_ptr(a); else I::set_last(B::next_ptr(a)); m_first = a; *B::prev_ptr(a) = &m_first; C::inc(); } inline void push_back(T *a) { T **last = I::get_last(); *B::next_ptr(a) = *last; *last = a; *B::prev_ptr(a) = last; I::set_last(B::next_ptr(a)); C::inc(); } inline void insert_after(T *pos, T *a) { if (pos == nullptr) push_front(a); else { *B::next_ptr(a) = *B::next_ptr(pos); *B::prev_ptr(a) = B::next_ptr(pos); *B::next_ptr(pos) = a; if (*B::next_ptr(a)) { T *old_next = *B::next_ptr(a); *B::prev_ptr(old_next) = B::next_ptr(a); } else I::set_last(B::next_ptr(a)); C::inc(); } } inline void remove(T *a) { T *next = *B::next_ptr(a); if (next) *B::prev_ptr(next) = *B::prev_ptr(a); else I::set_last(*B::prev_ptr(a)); **B::prev_ptr(a) = next; C::dec(); } inline T *front() { return m_first; } inline const T *front() const { return m_first; } inline T *pop_front() { T *result = front(); if (result) remove(result); return result; } void swap(I_P_List &rhs) { std::swap(m_first, rhs.m_first); I::swap(rhs); if (m_first) *B::prev_ptr(m_first) = &m_first; else I::set_last(&m_first); if (rhs.m_first) *B::prev_ptr(rhs.m_first) = &rhs.m_first; else I::set_last(&rhs.m_first); C::swap(rhs); } typedef B Adapter; typedef I_P_List Base; typedef I_P_List_iterator Iterator; typedef I_P_List_iterator Const_Iterator; friend class I_P_List_iterator; friend class I_P_List_iterator; }; /** Iterator for I_P_List. */ template class I_P_List_iterator { const L *list; T *current; public: I_P_List_iterator(const L &a) : list(&a), current(a.m_first) {} I_P_List_iterator(const L &a, T *current_arg) : list(&a), current(current_arg) {} inline void init(const L &a) { list = &a; current = a.m_first; } inline T *operator++(int) { T *result = current; if (result) current = *L::Adapter::next_ptr(current); return result; } inline T *operator++() { current = *L::Adapter::next_ptr(current); return current; } inline void rewind() { current = list->m_first; } }; /** Hook class which via its methods specifies which members of T should be used for participating in a intrusive list. */ template struct I_P_List_adapter { static inline T **next_ptr(T *el) { return &(el->*next); } static inline const T *const *next_ptr(const T *el) { return &(el->*next); } static inline T ***prev_ptr(T *el) { return &(el->*prev); } }; /** Element counting policy class for I_P_List to be used in cases when no element counting should be done. */ class I_P_List_null_counter { protected: void reset() {} void inc() {} void dec() {} void swap(I_P_List_null_counter &) {} }; /** Element counting policy class for I_P_List which provides basic element counting. */ class I_P_List_counter { uint m_counter; protected: I_P_List_counter() : m_counter(0) {} void reset() { m_counter = 0; } void inc() { m_counter++; } void dec() { m_counter--; } void swap(I_P_List_counter &rhs) { std::swap(m_counter, rhs.m_counter); } public: uint elements() const { return m_counter; } }; /** A null insertion policy class for I_P_List to be used in cases when push_back() operation is not necessary. */ template class I_P_List_no_push_back { protected: I_P_List_no_push_back(T **) {} void set_last(T **) {} /* T** get_last() const method is intentionally left unimplemented in order to prohibit usage of push_back() method in lists which use this policy. */ void swap(I_P_List_no_push_back &) {} }; /** An insertion policy class for I_P_List which can be used when fast push_back() operation is required. */ template class I_P_List_fast_push_back { T **m_last; protected: I_P_List_fast_push_back(T **a) : m_last(a) {} void set_last(T **a) { m_last = a; } T **get_last() const { return m_last; } void swap(I_P_List_fast_push_back &rhs) { std::swap(m_last, rhs.m_last); } }; #endif