LCOV - code coverage report
Current view: top level - src/detail - intrusive.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 44 44
Test Date: 2026-02-04 14:16:13 Functions: 100.0 % 32 32

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

Generated by: LCOV version 2.3