trackable.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // Boost.Signals library
  2. // Copyright Douglas Gregor 2001-2004. Use, modification and
  3. // distribution is subject to the Boost Software License, Version
  4. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // For more information, see http://www.boost.org
  7. #ifndef BOOST_SIGNALS_TRACKABLE_HPP
  8. #define BOOST_SIGNALS_TRACKABLE_HPP
  9. #include <boost/type_traits.hpp>
  10. #include <boost/signals/connection.hpp>
  11. #include <boost/ref.hpp>
  12. #include <boost/utility/addressof.hpp>
  13. #include <list>
  14. #include <vector>
  15. #ifdef BOOST_HAS_ABI_HEADERS
  16. # include BOOST_ABI_PREFIX
  17. #endif
  18. namespace boost {
  19. namespace BOOST_SIGNALS_NAMESPACE {
  20. // Base class for "trackable" objects that can be tracked when they are
  21. // bound in slot target functions. When a trackable object is destroyed,
  22. // the signal/slot connections are disconnected automatically.
  23. class BOOST_SIGNALS_DECL trackable {
  24. private:
  25. static void signal_disconnected(void* obj, void* data);
  26. friend class detail::signal_base_impl;
  27. friend class detail::slot_base;
  28. void signal_connected(connection, BOOST_SIGNALS_NAMESPACE::detail::bound_object&) const;
  29. protected:
  30. trackable() : connected_signals(), dying(false) {}
  31. trackable(const trackable&) : connected_signals(), dying(false) {}
  32. ~trackable();
  33. trackable& operator=(const trackable&)
  34. {
  35. dying = true;
  36. connected_signals.clear();
  37. dying = false;
  38. return *this;
  39. }
  40. private:
  41. typedef std::list<connection> connection_list;
  42. typedef connection_list::iterator connection_iterator;
  43. // List of connections that this object is part of
  44. mutable connection_list connected_signals;
  45. // True when the object is being destroyed
  46. mutable bool dying;
  47. };
  48. namespace detail {
  49. template<bool Cond> struct truth {};
  50. // A visitor that adds each trackable object to a vector
  51. class bound_objects_visitor {
  52. public:
  53. bound_objects_visitor(std::vector<const trackable*>& v) :
  54. bound_objects(v)
  55. {
  56. }
  57. template<typename T>
  58. void operator()(const T& t) const
  59. {
  60. decode(t, 0);
  61. }
  62. private:
  63. // decode() decides between a reference wrapper and anything else
  64. template<typename T>
  65. void decode(const reference_wrapper<T>& t, int) const
  66. {
  67. add_if_trackable(t.get_pointer());
  68. }
  69. template<typename T>
  70. void decode(const T& t, long) const
  71. {
  72. typedef truth<(is_pointer<T>::value)> is_a_pointer;
  73. maybe_get_pointer(t, is_a_pointer());
  74. }
  75. // maybe_get_pointer() decides between a pointer and a non-pointer
  76. template<typename T>
  77. void maybe_get_pointer(const T& t, truth<true>) const
  78. {
  79. add_if_trackable(t);
  80. }
  81. template<typename T>
  82. void maybe_get_pointer(const T& t, truth<false>) const
  83. {
  84. // Take the address of this object, because the object itself may be
  85. // trackable
  86. add_if_trackable(boost::addressof(t));
  87. }
  88. // add_if_trackable() adds trackable objects to the list of bound objects
  89. inline void add_if_trackable(const trackable* b) const
  90. {
  91. if (b) {
  92. bound_objects.push_back(b);
  93. }
  94. }
  95. inline void add_if_trackable(const void*) const { }
  96. template<typename R>
  97. inline void add_if_trackable(R (*)()) const { }
  98. template<typename R, typename T1>
  99. inline void add_if_trackable(R (*)(T1)) const { }
  100. template<typename R, typename T1, typename T2>
  101. inline void add_if_trackable(R (*)(T1, T2)) const { }
  102. template<typename R, typename T1, typename T2, typename T3>
  103. inline void add_if_trackable(R (*)(T1, T2, T3)) const { }
  104. template<typename R, typename T1, typename T2, typename T3, typename T4>
  105. inline void add_if_trackable(R (*)(T1, T2, T3, T4)) const { }
  106. template<typename R, typename T1, typename T2, typename T3, typename T4,
  107. typename T5>
  108. inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5)) const { }
  109. template<typename R, typename T1, typename T2, typename T3, typename T4,
  110. typename T5, typename T6>
  111. inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6)) const { }
  112. template<typename R, typename T1, typename T2, typename T3, typename T4,
  113. typename T5, typename T6, typename T7>
  114. inline void add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7)) const { }
  115. template<typename R, typename T1, typename T2, typename T3, typename T4,
  116. typename T5, typename T6, typename T7, typename T8>
  117. inline void
  118. add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7, T8)) const { }
  119. template<typename R, typename T1, typename T2, typename T3, typename T4,
  120. typename T5, typename T6, typename T7, typename T8, typename T9>
  121. inline void
  122. add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7, T8, T9)) const { }
  123. template<typename R, typename T1, typename T2, typename T3, typename T4,
  124. typename T5, typename T6, typename T7, typename T8, typename T9,
  125. typename T10>
  126. inline void
  127. add_if_trackable(R (*)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)) const { }
  128. std::vector<const trackable*>& bound_objects;
  129. };
  130. } // end namespace detail
  131. } // end namespace BOOST_SIGNALS_NAMESPACE
  132. } // end namespace boost
  133. #ifdef BOOST_HAS_ABI_HEADERS
  134. # include BOOST_ABI_SUFFIX
  135. #endif
  136. #endif // BOOST_SIGNALS_TRACKABLE_HPP