/* Owning version of intrusive_list for GDB, the GNU debugger. Copyright (C) 2024 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. 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 for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef GDBSUPPORT_OWNING_INTRUSIVE_LIST_H #define GDBSUPPORT_OWNING_INTRUSIVE_LIST_H #include "intrusive_list.h" /* An owning version of intrusive_list. */ template> class owning_intrusive_list : private intrusive_list { using base = intrusive_list; public: using value_type = typename base::value_type; using reference = typename base::reference; using iterator = typename base::iterator; using reverse_iterator = typename base::reverse_iterator; using const_iterator = typename base::const_iterator; using unique_pointer = std::unique_ptr; using base::iterator_to; using base::front; using base::back; using base::empty; using base::begin; using base::cbegin; using base::end; using base::cend; using base::rbegin; using base::crbegin; using base::rend; using base::crend; owning_intrusive_list () noexcept = default; owning_intrusive_list (owning_intrusive_list &&other) noexcept : base (std::move (other)) { } ~owning_intrusive_list () { this->clear (); } owning_intrusive_list &operator= (owning_intrusive_list &&other) noexcept { this->clear (); this->base::operator= (std::move (other)); return *this; } void swap (owning_intrusive_list &other) noexcept { this->base::swap (other); } /* Insert ELEM at the front of the list. The list takes ownership of ELEM. */ void push_front (unique_pointer elem) noexcept { this->base::push_front (*elem.release ()); } /* Insert ELEM at the back of the list. The list takes ownership of ELEM. */ void push_back (unique_pointer elem) noexcept { this->base::push_back (*elem.release ()); } /* Insert ELEM before POS in the list. The list takes ownership of ELEM. */ iterator insert (const_iterator pos, unique_pointer elem) noexcept { return this->base::insert (pos, *elem.release ()); } void splice (owning_intrusive_list &&other) noexcept { this->base::splice (std::move (other)); } /* Remove the element at the front of the list. The element is destroyed. */ void pop_front () noexcept { unique_pointer holder (&this->front ()); this->base::pop_front (); } /* Remove the element at the back of the list. The element is destroyed. */ void pop_back () noexcept { unique_pointer holder (&this->back ()); this->base::pop_back (); } /* Remove the element pointed by I from the list. The element pointed by I is destroyed. */ iterator erase (const_iterator i) noexcept { unique_pointer holder (&*i); return this->base::erase (i); } /* Remove all elements from the list. All elements are destroyed. */ void clear () noexcept { while (!this->empty ()) this->pop_front (); } /* Construct an element in-place at the front of the list. Return a reference to the new element. */ template reference emplace_front (Args &&...args) { return this->emplace (this->begin (), std::forward (args)...); } /* Construct an element in-place at the back of the list. Return a reference to the new element. */ template reference emplace_back (Args &&...args) { return this->emplace (this->end (), std::forward (args)...); } /* Construct an element in-place in the list, before POS. Return a reference to the new element. */ template reference emplace (const_iterator pos, Args &&...args) { return *this->insert (pos, std::make_unique (std::forward (args)...)); } /* Return type for the release method. */ struct release_ret { /* Iterator to the following element in the list. */ iterator next; /* The released element. */ unique_pointer released; }; release_ret release (const_iterator i) noexcept { iterator next = i; ++next; unique_pointer released (&*i); this->unlink_element (*i); return { next, std::move (released) }; } }; #endif /* GDBSUPPORT_OWNING_INTRUSIVE_LIST_H */