1 // Boost.Signals2 library
2 
3 // Copyright Frank Mori Hess 2007-2008.
4 // Copyright Timmo Stange 2007.
5 // Copyright Douglas Gregor 2001-2004. 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_BASE_HPP
13 #define BOOST_SIGNALS2_SLOT_BASE_HPP
14 
15 #include <boost/shared_ptr.hpp>
16 #include <boost/weak_ptr.hpp>
17 #include <boost/signals2/detail/foreign_ptr.hpp>
18 #include <boost/signals2/expired_slot.hpp>
19 #include <boost/signals2/signal_base.hpp>
20 #include <boost/throw_exception.hpp>
21 #include <boost/variant/apply_visitor.hpp>
22 #include <boost/variant/variant.hpp>
23 #include <vector>
24 
25 namespace boost
26 {
27   namespace signals2
28   {
29     namespace detail
30     {
31       class tracked_objects_visitor;
32       class trackable_pointee;
33 
34       typedef boost::variant<boost::weak_ptr<trackable_pointee>, boost::weak_ptr<void>, detail::foreign_void_weak_ptr > void_weak_ptr_variant;
35       typedef boost::variant<boost::shared_ptr<void>, detail::foreign_void_shared_ptr > void_shared_ptr_variant;
36       class lock_weak_ptr_visitor
37       {
38       public:
39         typedef void_shared_ptr_variant result_type;
40         template<typename WeakPtr>
operator ()(const WeakPtr & wp) const41         result_type operator()(const WeakPtr &wp) const
42         {
43           return wp.lock();
44         }
45         // overload to prevent incrementing use count of shared_ptr associated
46         // with signals2::trackable objects
operator ()(const weak_ptr<trackable_pointee> &) const47         result_type operator()(const weak_ptr<trackable_pointee> &) const
48         {
49           return boost::shared_ptr<void>();
50         }
51       };
52       class expired_weak_ptr_visitor
53       {
54       public:
55         typedef bool result_type;
56         template<typename WeakPtr>
operator ()(const WeakPtr & wp) const57         bool operator()(const WeakPtr &wp) const
58         {
59           return wp.expired();
60         }
61       };
62     }
63 
64     class slot_base
65     {
66     public:
67       typedef std::vector<detail::void_weak_ptr_variant> tracked_container_type;
68       typedef std::vector<detail::void_shared_ptr_variant> locked_container_type;
69 
tracked_objects() const70       const tracked_container_type& tracked_objects() const {return _tracked_objects;}
lock() const71       locked_container_type lock() const
72       {
73         locked_container_type locked_objects;
74         tracked_container_type::const_iterator it;
75         for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it)
76         {
77           locked_objects.push_back(apply_visitor(detail::lock_weak_ptr_visitor(), *it));
78           if(apply_visitor(detail::expired_weak_ptr_visitor(), *it))
79           {
80             boost::throw_exception(expired_slot());
81           }
82         }
83         return locked_objects;
84       }
expired() const85       bool expired() const
86       {
87         tracked_container_type::const_iterator it;
88         for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it)
89         {
90           if(apply_visitor(detail::expired_weak_ptr_visitor(), *it)) return true;
91         }
92         return false;
93       }
94     protected:
95       friend class detail::tracked_objects_visitor;
96 
track_signal(const signal_base & signal)97       void track_signal(const signal_base &signal)
98       {
99         _tracked_objects.push_back(signal.lock_pimpl());
100       }
101 
102       tracked_container_type _tracked_objects;
103     };
104   }
105 } // end namespace boost
106 
107 #endif // BOOST_SIGNALS2_SLOT_BASE_HPP
108