| // Boost.Signals2 library |
| |
| // Copyright Frank Mori Hess 2007-2008. |
| // Copyright Timmo Stange 2007. |
| // Copyright Douglas Gregor 2001-2004. Use, modification and |
| // distribution is subject to the Boost Software License, Version |
| // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| // For more information, see http://www.boost.org |
| |
| #ifndef BOOST_SIGNALS2_SLOT_BASE_HPP |
| #define BOOST_SIGNALS2_SLOT_BASE_HPP |
| |
| #include <boost/any.hpp> |
| #include <boost/shared_ptr.hpp> |
| #include <boost/weak_ptr.hpp> |
| #include <boost/signals2/detail/foreign_ptr.hpp> |
| #include <boost/signals2/expired_slot.hpp> |
| #include <boost/signals2/signal_base.hpp> |
| #include <boost/throw_exception.hpp> |
| #include <boost/variant/apply_visitor.hpp> |
| #include <boost/variant/variant.hpp> |
| #include <vector> |
| |
| namespace boost |
| { |
| namespace signals2 |
| { |
| namespace detail |
| { |
| class tracked_objects_visitor; |
| |
| typedef boost::variant<boost::weak_ptr<void>, detail::foreign_void_weak_ptr > void_weak_ptr_variant; |
| typedef boost::variant<boost::shared_ptr<void>, detail::foreign_void_shared_ptr > void_shared_ptr_variant; |
| class lock_weak_ptr_visitor |
| { |
| public: |
| typedef void_shared_ptr_variant result_type; |
| template<typename WeakPtr> |
| result_type operator()(const WeakPtr &wp) const |
| { |
| return wp.lock(); |
| } |
| }; |
| class expired_weak_ptr_visitor |
| { |
| public: |
| typedef bool result_type; |
| template<typename WeakPtr> |
| bool operator()(const WeakPtr &wp) const |
| { |
| return wp.expired(); |
| } |
| }; |
| } |
| |
| class slot_base |
| { |
| public: |
| typedef std::vector<detail::void_weak_ptr_variant> tracked_container_type; |
| typedef std::vector<detail::void_shared_ptr_variant> locked_container_type; |
| |
| const tracked_container_type& tracked_objects() const {return _tracked_objects;} |
| locked_container_type lock() const |
| { |
| locked_container_type locked_objects; |
| tracked_container_type::const_iterator it; |
| for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it) |
| { |
| locked_objects.push_back(apply_visitor(detail::lock_weak_ptr_visitor(), *it)); |
| if(apply_visitor(detail::expired_weak_ptr_visitor(), *it)) |
| { |
| boost::throw_exception(expired_slot()); |
| } |
| } |
| return locked_objects; |
| } |
| bool expired() const |
| { |
| tracked_container_type::const_iterator it; |
| for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it) |
| { |
| if(apply_visitor(detail::expired_weak_ptr_visitor(), *it)) return true; |
| } |
| return false; |
| } |
| protected: |
| friend class detail::tracked_objects_visitor; |
| |
| void track_signal(const signal_base &signal) |
| { |
| _tracked_objects.push_back(signal.lock_pimpl()); |
| } |
| |
| tracked_container_type _tracked_objects; |
| }; |
| } |
| } // end namespace boost |
| |
| #endif // BOOST_SIGNALS2_SLOT_BASE_HPP |