Blame boost/signals2/slot_base.hpp

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