/*
  boost::signals2::connection provides a handle to a signal/slot connection.

  Author: Frank Mori Hess <fmhess@users.sourceforge.net>
  Begin: 2007-01-23
*/
// Copyright Frank Mori Hess 2007-2008.
// Distributed under 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)

// See http://www.boost.org/libs/signals2 for library home page.

#ifndef BOOST_SIGNALS2_CONNECTION_HPP
#define BOOST_SIGNALS2_CONNECTION_HPP

#include <boost/function.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/signals2/detail/null_output_iterator.hpp>
#include <boost/signals2/detail/unique_lock.hpp>
#include <boost/signals2/slot.hpp>
#include <boost/weak_ptr.hpp>

namespace boost
{
  namespace signals2
  {
    extern inline void null_deleter(const void*) {}
    namespace detail
    {
      class connection_body_base
      {
      public:
        connection_body_base():
          _connected(true)
        {
        }
        virtual ~connection_body_base() {}
        void disconnect()
        {
          unique_lock<connection_body_base> lock(*this);
          nolock_disconnect();
        }
        void nolock_disconnect()
        {
          _connected = false;
        }
        virtual bool connected() const = 0;
        shared_ptr<void> get_blocker()
        {
          unique_lock<connection_body_base> lock(*this);
          shared_ptr<void> blocker = _weak_blocker.lock();
          if(blocker == shared_ptr<void>())
          {
            blocker.reset(this, &null_deleter);
            _weak_blocker = blocker;
          }
          return blocker;
        }
        bool blocked() const
        {
          return !_weak_blocker.expired();
        }
        bool nolock_nograb_blocked() const
        {
          return nolock_nograb_connected() == false || blocked();
        }
        bool nolock_nograb_connected() const {return _connected;}
        // expose part of Lockable concept of mutex
        virtual void lock() = 0;
        virtual void unlock() = 0;

      protected:

        mutable bool _connected;
        weak_ptr<void> _weak_blocker;
      };

      template<typename GroupKey, typename SlotType, typename Mutex>
      class connection_body: public connection_body_base
      {
      public:
        typedef Mutex mutex_type;
        connection_body(const SlotType &slot_in):
          slot(slot_in)
        {
        }
        virtual ~connection_body() {}
        virtual bool connected() const
        {
          unique_lock<mutex_type> lock(_mutex);
          nolock_grab_tracked_objects(detail::null_output_iterator());
          return nolock_nograb_connected();
        }
        const GroupKey& group_key() const {return _group_key;}
        void set_group_key(const GroupKey &key) {_group_key = key;}
        bool nolock_slot_expired() const
        {
          bool expired = slot.expired();
          if(expired == true)
          {
            _connected = false;
          }
          return expired;
        }
        template<typename OutputIterator>
          void nolock_grab_tracked_objects(OutputIterator inserter) const
        {
          slot_base::tracked_container_type::const_iterator it;
          for(it = slot.tracked_objects().begin();
            it != slot.tracked_objects().end();
            ++it)
          {
            void_shared_ptr_variant locked_object
            (
              apply_visitor
              (
                detail::lock_weak_ptr_visitor(),
                *it
              )
            );
            if(apply_visitor(detail::expired_weak_ptr_visitor(), *it))
            {
              _connected = false;
              return;
            }
            *inserter++ = locked_object;
          }
        }
        // expose Lockable concept of mutex
        virtual void lock()
        {
          _mutex.lock();
        }
        virtual void unlock()
        {
          _mutex.unlock();
        }
        SlotType slot;
      private:
        mutable mutex_type _mutex;
        GroupKey _group_key;
      };
    }

    class shared_connection_block;

    class connection
    {
    public:
      friend class shared_connection_block;

      connection() {}
      connection(const connection &other): _weak_connection_body(other._weak_connection_body)
      {}
      connection(const boost::weak_ptr<detail::connection_body_base> &connectionBody):
        _weak_connection_body(connectionBody)
      {}
      ~connection() {}
      void disconnect() const
      {
        boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
        if(connectionBody == 0) return;
        connectionBody->disconnect();
      }
      bool connected() const
      {
        boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
        if(connectionBody == 0) return false;
        return connectionBody->connected();
      }
      bool blocked() const
      {
        boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
        if(connectionBody == 0) return true;
        return connectionBody->blocked();
      }
      bool operator==(const connection& other) const
      {
        boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
        boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock());
        return connectionBody == otherConnectionBody;
      }
      bool operator!=(const connection& other) const
      {
        return !(*this == other);
      }
      bool operator<(const connection& other) const
      {
        boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
        boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock());
        return connectionBody < otherConnectionBody;
      }
      void swap(connection &other)
      {
        using std::swap;
        swap(_weak_connection_body, other._weak_connection_body);
      }
    protected:

      boost::weak_ptr<detail::connection_body_base> _weak_connection_body;
    };
    inline void swap(connection &conn1, connection &conn2)
    {
      conn1.swap(conn2);
    }

    class scoped_connection: public connection
    {
    public:
      scoped_connection() {}
      scoped_connection(const connection &other):
        connection(other)
      {}
      ~scoped_connection()
      {
        disconnect();
      }
      scoped_connection& operator=(const connection &rhs)
      {
        disconnect();
        connection::operator=(rhs);
        return *this;
      }
      connection release()
      {
        connection conn(_weak_connection_body);
        _weak_connection_body.reset();
        return conn;
      }
    private:
      scoped_connection(const scoped_connection &other);
      scoped_connection& operator=(const scoped_connection &rhs);
    };
    // Sun 5.9 compiler doesn't find the swap for base connection class when
    // arguments are scoped_connection, so we provide this explicitly.
    inline void swap(scoped_connection &conn1, scoped_connection &conn2)
    {
      conn1.swap(conn2);
    }
  }
}

#endif  // BOOST_SIGNALS2_CONNECTION_HPP
