LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/signals2/detail - slot_call_iterator.hpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 63 71 88.7 %
Date: 2026-06-25 07:23:51 Functions: 104 168 61.9 %

          Line data    Source code
       1             : // Boost.Signals2 library
       2             : 
       3             : // Copyright Douglas Gregor 2001-2004.
       4             : // Copyright Frank Mori Hess 2007-2008.
       5             : // Use, modification and
       6             : // distribution is subject to the Boost Software License, Version
       7             : // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
       8             : // http://www.boost.org/LICENSE_1_0.txt)
       9             : 
      10             : // For more information, see http://www.boost.org
      11             : 
      12             : #ifndef BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
      13             : #define BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
      14             : 
      15             : #include <boost/assert.hpp>
      16             : #include <boost/core/no_exceptions_support.hpp>
      17             : #include <boost/iterator/iterator_facade.hpp>
      18             : #include <boost/optional.hpp>
      19             : #include <boost/scoped_ptr.hpp>
      20             : #include <boost/signals2/connection.hpp>
      21             : #include <boost/signals2/slot_base.hpp>
      22             : #include <boost/signals2/detail/auto_buffer.hpp>
      23             : #include <boost/signals2/detail/unique_lock.hpp>
      24             : #include <boost/type_traits/add_const.hpp>
      25             : #include <boost/type_traits/add_reference.hpp>
      26             : #include <boost/type_traits/aligned_storage.hpp>
      27             : #include <boost/weak_ptr.hpp>
      28             : 
      29             : namespace boost {
      30             :   namespace signals2 {
      31             :     namespace detail {
      32             :       template<typename ResultType, typename Function>
      33             :         class slot_call_iterator_cache
      34             :       {
      35             :       public:
      36      164664 :         slot_call_iterator_cache(const Function &f_arg):
      37       82332 :           f(f_arg),
      38       82332 :           connected_slot_count(0),
      39       82332 :           disconnected_slot_count(0),
      40       82332 :           m_active_slot(0)
      41      164664 :         {}
      42             : 
      43      164664 :         ~slot_call_iterator_cache()
      44       82332 :         {
      45       82332 :           if(m_active_slot)
      46             :           {
      47           0 :             garbage_collecting_lock<connection_body_base> lock(*m_active_slot);
      48           0 :             m_active_slot->dec_slot_refcount(lock);
      49           0 :           }
      50      164664 :         }
      51             : 
      52             :         template<typename M>
      53         470 :         void set_active_slot(garbage_collecting_lock<M> &lock,
      54             :           connection_body_base *active_slot)
      55             :         {
      56         470 :           if(m_active_slot)
      57         235 :             m_active_slot->dec_slot_refcount(lock);
      58         470 :           m_active_slot = active_slot;
      59         470 :           if(m_active_slot)
      60         235 :             m_active_slot->inc_slot_refcount(lock);
      61         470 :         }
      62             : 
      63             :         optional<ResultType> result;
      64             :         typedef auto_buffer<void_shared_ptr_variant, store_n_objects<10> > tracked_ptrs_type;
      65             :         tracked_ptrs_type tracked_ptrs;
      66             :         Function f;
      67             :         unsigned connected_slot_count;
      68             :         unsigned disconnected_slot_count;
      69             :         connection_body_base *m_active_slot;
      70             :       };
      71             : 
      72             :       // Generates a slot call iterator. Essentially, this is an iterator that:
      73             :       //   - skips over disconnected slots in the underlying list
      74             :       //   - calls the connected slots when dereferenced
      75             :       //   - caches the result of calling the slots
      76             :       template<typename Function, typename Iterator, typename ConnectionBody>
      77             :       class slot_call_iterator_t
      78             :         : public boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
      79             :         typename Function::result_type,
      80             :         boost::single_pass_traversal_tag>
      81             :       {
      82             :         typedef boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
      83             :           typename Function::result_type,
      84             :           boost::single_pass_traversal_tag>
      85             :         inherited;
      86             : 
      87             :         typedef typename Function::result_type result_type;
      88             : 
      89             :         typedef slot_call_iterator_cache<result_type, Function> cache_type;
      90             : 
      91             :         friend class boost::iterator_core_access;
      92             : 
      93             :       public:
      94      329328 :         slot_call_iterator_t(Iterator iter_in, Iterator end_in,
      95             :           cache_type &c):
      96      164664 :           iter(iter_in), end(end_in),
      97      164664 :           cache(&c), callable_iter(end_in)
      98      164664 :         {
      99      164664 :           lock_next_callable();
     100      329328 :         }
     101             : 
     102             :         typename inherited::reference
     103         235 :         dereference() const
     104             :         {
     105         235 :           if (!cache->result) {
     106             :             BOOST_TRY
     107             :             {
     108         235 :               cache->result = cache->f(*iter);
     109         235 :             }
     110             :             BOOST_CATCH(expired_slot &)
     111             :             {
     112           0 :               (*iter)->disconnect();
     113           0 :               BOOST_RETHROW
     114           0 :             }
     115             :             BOOST_CATCH_END
     116         235 :           }
     117         235 :           return cache->result.get();
     118           0 :         }
     119             : 
     120         235 :         void increment()
     121             :         {
     122         235 :           ++iter;
     123         235 :           lock_next_callable();
     124         235 :           cache->result.reset();
     125         235 :         }
     126             : 
     127       82567 :         bool equal(const slot_call_iterator_t& other) const
     128             :         {
     129       82567 :           return iter == other.iter;
     130             :         }
     131             : 
     132             :       private:
     133             :         typedef garbage_collecting_lock<connection_body_base> lock_type;
     134             : 
     135         470 :         void set_callable_iter(lock_type &lock, Iterator newValue) const
     136             :         {
     137         470 :           callable_iter = newValue;
     138         470 :           if(callable_iter == end)
     139         235 :             cache->set_active_slot(lock, 0);
     140             :           else
     141         235 :             cache->set_active_slot(lock, (*callable_iter).get());
     142         470 :         }
     143             : 
     144      164899 :         void lock_next_callable() const
     145             :         {
     146      164899 :           if(iter == callable_iter)
     147             :           {
     148      164429 :             return;
     149             :           }
     150             :   
     151         470 :           for(;iter != end; ++iter)
     152             :           {
     153         235 :             cache->tracked_ptrs.clear();
     154         235 :             lock_type lock(**iter);
     155         235 :             (*iter)->nolock_grab_tracked_objects(lock, std::back_inserter(cache->tracked_ptrs));
     156         235 :             if((*iter)->nolock_nograb_connected())
     157             :             {
     158         235 :               ++cache->connected_slot_count;
     159         235 :             }else
     160             :             {
     161           0 :               ++cache->disconnected_slot_count;
     162             :             }
     163         235 :             if((*iter)->nolock_nograb_blocked() == false)
     164             :             {
     165         235 :               set_callable_iter(lock, iter);
     166         235 :               break;
     167             :             }
     168         235 :           }
     169             :           
     170         470 :           if(iter == end)
     171             :           {
     172         235 :             if(callable_iter != end)
     173             :             {
     174         235 :               lock_type lock(**callable_iter);
     175         235 :               set_callable_iter(lock, end);
     176         235 :             }
     177         235 :           }
     178      164899 :         }
     179             : 
     180             :         mutable Iterator iter;
     181             :         Iterator end;
     182             :         cache_type *cache;
     183             :         mutable Iterator callable_iter;
     184             :       };
     185             :     } // end namespace detail
     186             :   } // end namespace BOOST_SIGNALS_NAMESPACE
     187             : } // end namespace boost
     188             : 
     189             : #endif // BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP

Generated by: LCOV version 1.16