slot_call_iterator.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Boost.Signals2 library
  2. // Copyright Douglas Gregor 2001-2004.
  3. // Copyright Frank Mori Hess 2007-2008.
  4. // Use, modification and
  5. // distribution is subject to the Boost Software License, Version
  6. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. // For more information, see http://www.boost.org
  9. #ifndef BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
  10. #define BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
  11. #include <boost/assert.hpp>
  12. #include <boost/aligned_storage.hpp>
  13. #include <boost/iterator/iterator_facade.hpp>
  14. #include <boost/optional.hpp>
  15. #include <boost/scoped_ptr.hpp>
  16. #include <boost/signals2/connection.hpp>
  17. #include <boost/signals2/slot_base.hpp>
  18. #include <boost/signals2/detail/auto_buffer.hpp>
  19. #include <boost/signals2/detail/unique_lock.hpp>
  20. #include <boost/weak_ptr.hpp>
  21. namespace boost {
  22. namespace signals2 {
  23. namespace detail {
  24. template<typename ResultType, typename Function>
  25. class slot_call_iterator_cache
  26. {
  27. public:
  28. slot_call_iterator_cache(const Function &f_arg):
  29. f(f_arg),
  30. connected_slot_count(0),
  31. disconnected_slot_count(0)
  32. {}
  33. optional<ResultType> result;
  34. typedef auto_buffer<void_shared_ptr_variant, store_n_objects<10> > tracked_ptrs_type;
  35. tracked_ptrs_type tracked_ptrs;
  36. Function f;
  37. unsigned connected_slot_count;
  38. unsigned disconnected_slot_count;
  39. };
  40. // Generates a slot call iterator. Essentially, this is an iterator that:
  41. // - skips over disconnected slots in the underlying list
  42. // - calls the connected slots when dereferenced
  43. // - caches the result of calling the slots
  44. template<typename Function, typename Iterator, typename ConnectionBody>
  45. class slot_call_iterator_t
  46. : public boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
  47. typename Function::result_type,
  48. boost::single_pass_traversal_tag,
  49. typename Function::result_type const&>
  50. {
  51. typedef boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
  52. typename Function::result_type,
  53. boost::single_pass_traversal_tag,
  54. typename Function::result_type const&>
  55. inherited;
  56. typedef typename Function::result_type result_type;
  57. friend class boost::iterator_core_access;
  58. public:
  59. slot_call_iterator_t(Iterator iter_in, Iterator end_in,
  60. slot_call_iterator_cache<result_type, Function> &c):
  61. iter(iter_in), end(end_in),
  62. cache(&c), callable_iter(end_in)
  63. {
  64. lock_next_callable();
  65. }
  66. typename inherited::reference
  67. dereference() const
  68. {
  69. if (!cache->result) {
  70. try
  71. {
  72. cache->result.reset(cache->f(*iter));
  73. }
  74. catch(expired_slot &)
  75. {
  76. (*iter)->disconnect();
  77. throw;
  78. }
  79. }
  80. return cache->result.get();
  81. }
  82. void increment()
  83. {
  84. ++iter;
  85. lock_next_callable();
  86. cache->result.reset();
  87. }
  88. bool equal(const slot_call_iterator_t& other) const
  89. {
  90. return iter == other.iter;
  91. }
  92. private:
  93. typedef unique_lock<connection_body_base> lock_type;
  94. void lock_next_callable() const
  95. {
  96. if(iter == callable_iter)
  97. {
  98. return;
  99. }
  100. for(;iter != end; ++iter)
  101. {
  102. lock_type lock(**iter);
  103. cache->tracked_ptrs.clear();
  104. (*iter)->nolock_grab_tracked_objects(std::back_inserter(cache->tracked_ptrs));
  105. if((*iter)->nolock_nograb_connected())
  106. {
  107. ++cache->connected_slot_count;
  108. }else
  109. {
  110. ++cache->disconnected_slot_count;
  111. }
  112. if((*iter)->nolock_nograb_blocked() == false)
  113. {
  114. callable_iter = iter;
  115. break;
  116. }
  117. }
  118. if(iter == end)
  119. {
  120. callable_iter = end;
  121. }
  122. }
  123. mutable Iterator iter;
  124. Iterator end;
  125. slot_call_iterator_cache<result_type, Function> *cache;
  126. mutable Iterator callable_iter;
  127. };
  128. } // end namespace detail
  129. } // end namespace BOOST_SIGNALS_NAMESPACE
  130. } // end namespace boost
  131. #endif // BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP