Home | History | Annotate | Line # | Download | only in gdbsupport
      1 /* Owning version of intrusive_list for GDB, the GNU debugger.
      2    Copyright (C) 2024 Free Software Foundation, Inc.
      3 
      4    This file is part of GDB.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3 of the License, or
      9    (at your option) any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18 
     19 #ifndef GDBSUPPORT_OWNING_INTRUSIVE_LIST_H
     20 #define GDBSUPPORT_OWNING_INTRUSIVE_LIST_H
     21 
     22 #include "intrusive_list.h"
     23 
     24 /* An owning version of intrusive_list.  */
     25 
     26 template<typename T, typename AsNode = intrusive_base_node<T>>
     27 class owning_intrusive_list : private intrusive_list<T, AsNode>
     28 {
     29   using base = intrusive_list<T, AsNode>;
     30 
     31 public:
     32   using value_type = typename base::value_type;
     33   using reference = typename base::reference;
     34   using iterator = typename base::iterator;
     35   using reverse_iterator = typename base::reverse_iterator;
     36   using const_iterator = typename base::const_iterator;
     37   using unique_pointer = std::unique_ptr<T>;
     38 
     39   using base::iterator_to;
     40   using base::front;
     41   using base::back;
     42   using base::empty;
     43   using base::begin;
     44   using base::cbegin;
     45   using base::end;
     46   using base::cend;
     47   using base::rbegin;
     48   using base::crbegin;
     49   using base::rend;
     50   using base::crend;
     51 
     52   owning_intrusive_list () noexcept = default;
     53 
     54   owning_intrusive_list (owning_intrusive_list &&other) noexcept
     55     : base (std::move (other))
     56   {
     57   }
     58 
     59   ~owning_intrusive_list ()
     60   { this->clear (); }
     61 
     62   owning_intrusive_list &operator= (owning_intrusive_list &&other) noexcept
     63   {
     64     this->clear ();
     65     this->base::operator= (std::move (other));
     66     return *this;
     67   }
     68 
     69   void swap (owning_intrusive_list &other) noexcept
     70   { this->base::swap (other); }
     71 
     72   /* Insert ELEM at the front of the list.
     73 
     74      The list takes ownership of ELEM.  */
     75   void push_front (unique_pointer elem) noexcept
     76   { this->base::push_front (*elem.release ()); }
     77 
     78   /* Insert ELEM at the back of the list.
     79 
     80      The list takes ownership of ELEM.  */
     81   void push_back (unique_pointer elem) noexcept
     82   { this->base::push_back (*elem.release ()); }
     83 
     84   /* Insert ELEM before POS in the list.
     85 
     86      The list takes ownership of ELEM.  */
     87   iterator insert (const_iterator pos, unique_pointer elem) noexcept
     88   { return  this->base::insert (pos, *elem.release ());  }
     89 
     90   void splice (owning_intrusive_list &&other) noexcept
     91   { this->base::splice (std::move (other)); }
     92 
     93   /* Remove the element at the front of the list.  The element is destroyed.  */
     94   void pop_front () noexcept
     95   {
     96     unique_pointer holder (&this->front ());
     97     this->base::pop_front ();
     98   }
     99 
    100   /* Remove the element at the back of the list.  The element is destroyed.  */
    101   void pop_back () noexcept
    102   {
    103     unique_pointer holder (&this->back ());
    104     this->base::pop_back ();
    105   }
    106 
    107   /* Remove the element pointed by I from the list.  The element
    108      pointed by I is destroyed.  */
    109   iterator erase (const_iterator i) noexcept
    110   {
    111     unique_pointer holder (&*i);
    112     return this->base::erase (i);
    113   }
    114 
    115   /* Remove all elements from the list.  All elements are destroyed.  */
    116   void clear () noexcept
    117   {
    118     while (!this->empty ())
    119       this->pop_front ();
    120   }
    121 
    122   /* Construct an element in-place at the front of the list.
    123 
    124      Return a reference to the new element.  */
    125   template<typename... Args>
    126   reference emplace_front (Args &&...args)
    127   { return this->emplace (this->begin (), std::forward<Args> (args)...); }
    128 
    129   /* Construct an element in-place at the back of the list.
    130 
    131      Return a reference to the new element.  */
    132   template<typename... Args>
    133   reference emplace_back (Args &&...args)
    134   { return this->emplace (this->end (), std::forward<Args> (args)...); }
    135 
    136   /* Construct an element in-place in the list, before POS.
    137 
    138      Return a reference to the new element.  */
    139   template<typename... Args>
    140   reference emplace (const_iterator pos, Args &&...args)
    141   {
    142     return *this->insert (pos,
    143 			 std::make_unique<T> (std::forward<Args> (args)...));
    144   }
    145 
    146   /* Return type for the release method.  */
    147   struct release_ret
    148   {
    149     /* Iterator to the following element in the list.  */
    150     iterator next;
    151 
    152     /* The released element.  */
    153     unique_pointer released;
    154   };
    155 
    156   release_ret release (const_iterator i) noexcept
    157   {
    158     iterator next = i;
    159     ++next;
    160     unique_pointer released (&*i);
    161 
    162     this->unlink_element (*i);
    163 
    164     return { next, std::move (released) };
    165   }
    166 };
    167 
    168 #endif /* GDBSUPPORT_OWNING_INTRUSIVE_LIST_H */
    169