LCOV - code coverage report
Current view: top level - capy/detail - intrusive.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 81 81
Test Date: 2026-06-09 22:00:30 Functions: 100.0 % 21 21

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : //
       4                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6                 : //
       7                 : // Official repository: https://github.com/cppalliance/capy
       8                 : //
       9                 : 
      10                 : #ifndef BOOST_CAPY_DETAIL_INTRUSIVE_HPP
      11                 : #define BOOST_CAPY_DETAIL_INTRUSIVE_HPP
      12                 : 
      13                 : namespace boost {
      14                 : namespace capy {
      15                 : namespace detail {
      16                 : 
      17                 : //------------------------------------------------
      18                 : 
      19                 : /** An intrusive doubly linked list.
      20                 : 
      21                 :     This container provides O(1) push and pop operations for
      22                 :     elements that derive from @ref node. Elements are not
      23                 :     copied or moved; they are linked directly into the list.
      24                 : 
      25                 :     @tparam T The element type. Must derive from `intrusive_list<T>::node`.
      26                 : */
      27                 : template<class T>
      28                 : class intrusive_list
      29                 : {
      30                 : public:
      31                 :     /** Base class for list elements.
      32                 : 
      33                 :         Derive from this class to make a type usable with
      34                 :         @ref intrusive_list. The `next_` and `prev_` pointers
      35                 :         are private and accessible only to the list.
      36                 :     */
      37                 :     class node
      38                 :     {
      39                 :         friend class intrusive_list;
      40                 : 
      41                 :     private:
      42                 :         T* next_;
      43                 :         T* prev_;
      44                 :         bool linked_ = false;
      45                 :     };
      46                 : 
      47                 : private:
      48                 :     T* head_ = nullptr;
      49                 :     T* tail_ = nullptr;
      50                 : 
      51                 : public:
      52 HIT          31 :     intrusive_list() = default;
      53                 : 
      54               2 :     intrusive_list(intrusive_list&& other) noexcept
      55               2 :         : head_(other.head_)
      56               2 :         , tail_(other.tail_)
      57                 :     {
      58               2 :         other.head_ = nullptr;
      59               2 :         other.tail_ = nullptr;
      60               2 :     }
      61                 : 
      62                 :     intrusive_list(intrusive_list const&) = delete;
      63                 :     intrusive_list& operator=(intrusive_list const&) = delete;
      64                 :     intrusive_list& operator=(intrusive_list&&) = delete;
      65                 : 
      66                 :     bool
      67              36 :     empty() const noexcept
      68                 :     {
      69              36 :         return head_ == nullptr;
      70                 :     }
      71                 : 
      72                 :     void
      73           11512 :     push_back(T* w) noexcept
      74                 :     {
      75           11512 :         w->next_ = nullptr;
      76           11512 :         w->prev_ = tail_;
      77           11512 :         if(tail_)
      78           11441 :             tail_->next_ = w;
      79                 :         else
      80              71 :             head_ = w;
      81           11512 :         tail_ = w;
      82           11512 :         w->linked_ = true;
      83           11512 :     }
      84                 : 
      85                 :     void
      86               4 :     splice_back(intrusive_list& other) noexcept
      87                 :     {
      88               4 :         if(other.empty())
      89               2 :             return;
      90               2 :         if(tail_)
      91                 :         {
      92               1 :             tail_->next_ = other.head_;
      93               1 :             other.head_->prev_ = tail_;
      94               1 :             tail_ = other.tail_;
      95                 :         }
      96                 :         else
      97                 :         {
      98               1 :             head_ = other.head_;
      99               1 :             tail_ = other.tail_;
     100                 :         }
     101               2 :         other.head_ = nullptr;
     102               2 :         other.tail_ = nullptr;
     103                 :     }
     104                 : 
     105                 :     T*
     106             121 :     pop_front() noexcept
     107                 :     {
     108             121 :         if(!head_)
     109              69 :             return nullptr;
     110              52 :         T* w = head_;
     111              52 :         head_ = head_->next_;
     112              52 :         if(head_)
     113              22 :             head_->prev_ = nullptr;
     114                 :         else
     115              30 :             tail_ = nullptr;
     116              52 :         w->linked_ = false;
     117              52 :         return w;
     118                 :     }
     119                 : 
     120                 :     void
     121           11461 :     remove(T* w) noexcept
     122                 :     {
     123           11461 :         if(!w->linked_)
     124               1 :             return;
     125           11460 :         if(w->prev_)
     126               7 :             w->prev_->next_ = w->next_;
     127                 :         else
     128           11453 :             head_ = w->next_;
     129           11460 :         if(w->next_)
     130           11415 :             w->next_->prev_ = w->prev_;
     131                 :         else
     132              45 :             tail_ = w->prev_;
     133           11460 :         w->linked_ = false;
     134                 :     }
     135                 : };
     136                 : 
     137                 : //------------------------------------------------
     138                 : 
     139                 : /** An intrusive singly linked FIFO queue.
     140                 : 
     141                 :     This container provides O(1) push and pop operations for
     142                 :     elements that derive from @ref node. Elements are not
     143                 :     copied or moved; they are linked directly into the queue.
     144                 : 
     145                 :     Unlike @ref intrusive_list, this uses only a single `next_`
     146                 :     pointer per node, saving memory at the cost of not supporting
     147                 :     O(1) removal of arbitrary elements.
     148                 : 
     149                 :     @tparam T The element type. Must derive from `intrusive_queue<T>::node`.
     150                 : */
     151                 : template<class T>
     152                 : class intrusive_queue
     153                 : {
     154                 : public:
     155                 :     /** Base class for queue elements.
     156                 : 
     157                 :         Derive from this class to make a type usable with
     158                 :         @ref intrusive_queue. The `next_` pointer is private
     159                 :         and accessible only to the queue.
     160                 :     */
     161                 :     class node
     162                 :     {
     163                 :         friend class intrusive_queue;
     164                 : 
     165                 :     private:
     166                 :         T* next_;
     167                 :     };
     168                 : 
     169                 : private:
     170                 :     T* head_ = nullptr;
     171                 :     T* tail_ = nullptr;
     172                 : 
     173                 : public:
     174                 :     intrusive_queue() = default;
     175                 : 
     176               2 :     intrusive_queue(intrusive_queue&& other) noexcept
     177               2 :         : head_(other.head_)
     178               2 :         , tail_(other.tail_)
     179                 :     {
     180               2 :         other.head_ = nullptr;
     181               2 :         other.tail_ = nullptr;
     182               2 :     }
     183                 : 
     184                 :     intrusive_queue(intrusive_queue const&) = delete;
     185                 :     intrusive_queue& operator=(intrusive_queue const&) = delete;
     186                 :     intrusive_queue& operator=(intrusive_queue&&) = delete;
     187                 : 
     188                 :     bool
     189              27 :     empty() const noexcept
     190                 :     {
     191              27 :         return head_ == nullptr;
     192                 :     }
     193                 : 
     194                 :     void
     195              18 :     push(T* w) noexcept
     196                 :     {
     197              18 :         w->next_ = nullptr;
     198              18 :         if(tail_)
     199               8 :             tail_->next_ = w;
     200                 :         else
     201              10 :             head_ = w;
     202              18 :         tail_ = w;
     203              18 :     }
     204                 : 
     205                 :     void
     206               4 :     splice(intrusive_queue& other) noexcept
     207                 :     {
     208               4 :         if(other.empty())
     209               2 :             return;
     210               2 :         if(tail_)
     211               1 :             tail_->next_ = other.head_;
     212                 :         else
     213               1 :             head_ = other.head_;
     214               2 :         tail_ = other.tail_;
     215               2 :         other.head_ = nullptr;
     216               2 :         other.tail_ = nullptr;
     217                 :     }
     218                 : 
     219                 :     T*
     220              21 :     pop() noexcept
     221                 :     {
     222              21 :         if(!head_)
     223               3 :             return nullptr;
     224              18 :         T* w = head_;
     225              18 :         head_ = head_->next_;
     226              18 :         if(!head_)
     227               9 :             tail_ = nullptr;
     228              18 :         return w;
     229                 :     }
     230                 : };
     231                 : 
     232                 : } // detail
     233                 : } // capy
     234                 : } // boost
     235                 : 
     236                 : #endif
        

Generated by: LCOV version 2.3