boost代码分析:signal中的connect过程(上)

connect 过程中 slot 的创建

    template<
        typename R,
        typename T1, typename T2
        ,
        typename Combiner,
        typename Group,
        typename GroupCompare,
        typename SlotFunction
    >
    signals::connection
    signal2<
    R, T1, T2
    ,
    Combiner, Group, GroupCompare, SlotFunction
    >::connect(const slot_type& in_slot,
    signals::connect_position at)
    {
        using boost::signals::detail::stored_group;



        if (!in_slot.is_active()) {
            return signals::connection();
        }

        return impl->connect_slot(in_slot.get_slot_function(), stored_group(),
            in_slot.get_data(), at);
    }


    template<
        typename R,
        typename T1, typename T2
        ,
        typename Combiner = last_value<R>,
        typename Group = int,
        typename GroupCompare = std::less<Group>,
        typename SlotFunction = function2<
        R ,
        T1, T2>
    >
    class signal2 :
        public signals::detail::signal_base,
        public signals::trackable
    {
    public:

        typedef SlotFunction slot_function_type;


        typedef typename signals::detail::slot_result_type<R>::type
            slot_result_type;


        typedef T1 arg2_type; typedef T2 arg3_type;




        typedef T1 first_argument_type;
        typedef T2 second_argument_type;


    private:

        typedef signals::detail::group_bridge_compare<GroupCompare, Group>
            real_group_compare_type;



        typedef signals::detail::call_bound2<R>
            outer_bound_slot_caller;
        typedef typename outer_bound_slot_caller::template
            caller<T1, T2
            ,
            slot_function_type>
            call_bound_slot;

    public:

        typedef typename Combiner::result_type result_type;


        typedef Combiner combiner_type;


       typedef slot<slot_function_type> slot_type;


        typedef Group group_type;
        typedef GroupCompare group_compare_type;

        typedef signals::detail::slot_call_iterator<
            call_bound_slot, iterator> slot_call_iterator;

        explicit
            signal2(const Combiner& c = Combiner(),
            const GroupCompare& comp = GroupCompare()) :
        signals::detail::signal_base(real_group_compare_type(comp),
            c)
        {
        }


        signals::connection
            connect(const slot_type&,
            signals::connect_position at
            = signals::at_back);


        signals::connection
            connect(const group_type&, const slot_type&,
            signals::connect_position at
            = signals::at_back);
# 220 "/home/Administrator/boost_1_34_1/boost/signals/signaltemplate.hpp"
        template<typename T>
            void disconnect(const T& t)
        {
            typedef mpl::bool
<(is_convertible<T, group_type>::value)> is_group;
            this->do_disconnect(t, is_group());
        }

    private:

        void do_disconnect(const grouptype& group, mpl::bool<true>)
        {
            impl->disconnect(group);
        }

        template<typename Function>
            void dodisconnect(const Function& f, mpl::bool<false>)
        {

            signals::detail::callnotification notification(this->impl);

            for (iterator i = impl->slots
.begin(); i != impl->slots_.end(); ++i) {
                slot_function_type& s = unsafe_any_cast<slot_function_type>(&i->second);
                if (s == f) i->first.disconnect();
            }
        }


    public:


        result_type operator()(T1 a1, T2 a2);
        result_type operator()(T1 a1, T2 a2) const;

        Combiner& combiner()
        { return
unsafe_anycast<Combiner>(&impl->combiner); }

        const Combiner& combiner() const
        { return unsafe_anycast<const Combiner>(&impl->combiner); }
    };


template<typename SlotFunction>
class slot : public signals::detail::slot_base {
    typedef signals::detail::slot_base inherited;
    typedef typename inherited::data_t data_t;

public:
    template<typename F>
    slot(const F& f) : slot_function(signals::get_invocable_slot(f, signals::tag_type(f)))
    {
      this->data.reset(new data_t);





      signals::detail::bound_objects_visitor
        do_bind(this->data->bound_objects);
      visit_each(do_bind,
                 signals::get_inspectable_slot
                   (f, signals::tag_type(f)));
      create_connection();
    }
# 139 "slot.hpp"
public:

    const SlotFunction& get_slot_function() const { return slot_function; }

    void release() const { data->watch_bound_objects.set_controlling(false); }

private:
    slot();
    slot& operator=(const slot&);

    SlotFunction slot_function;
};


class slot_base {
      public:
        struct data_t {
          std::vector<const trackable
> bound_objects;
          connection watch_bound_objects;
        };
        shared_ptr<data_t> get_data() const { return data; }


        std::vector<const trackable>& get_bound_objects() const
        { return data->bound_objects; }



        bool is_active() const
        { return data->watch_bound_objects.connected(); }

      protected:

        void create_connection();

        shared_ptr<data_t> data;

      private:
        static void bound_object_destructed(void
, void) {}
};


    template<typename Visitor, typename T>
        inline void visit_each(Visitor& visitor, const T& t, long)
    {
        visitor(t);
    }

    template<typename Visitor, typename T>
        inline void visit_each(Visitor& visitor, const T& t)
    {
        visit_each(visitor, t, 0);
    }

// bind.hpp   当 T 为 bind 类型时的特化,负责添加 bind 中的所有 trackable 的子对象
template<class V, class R, class F, class L> void visit_each( V & v, bind_t<R, F, L> const & t, int )
{
    t.accept( v );
}


    template<bool Cond> struct truth {};


    class bound_objects_visitor {
    public:
      bound_objects_visitor(std::vector<const trackable
>& v) :
        bound_objects(v)
      {
      }

      template<typename T>
      void operator()(const T& t) const
      {
        decode(t, 0);
      }

    private:

      template<typename T>
      void decode(const reference_wrapper<T>& t, int) const
      {
        add_if_trackable(t.get_pointer());
      }

      template<typename T>
      void decode(const T& t, long) const
      {
        typedef truth<(is_pointer<T>::value)> is_a_pointer;
        maybe_get_pointer(t, is_a_pointer());
      }


      template<typename T>
      void maybe_get_pointer(const T& t, truth<true>) const
      {
        add_if_trackable(t);
      }

      template<typename T>
      void maybe_get_pointer(const T& t, truth<false>) const
      {


        add_if_trackable(boost::addressof(t));
      }


      inline void add_if_trackable(const trackable b) const
      {
        if (b) {
          bound_objects.push_back(b);
        }
      }

      inline void add_if_trackable(const void
) const
      {
      }

      template<typename R>
      inline void add_if_trackable(R ()()) const
      {
      }

      template<typename R, typename T1>
      inline void add_if_trackable(R (
)(T1)) const
      {
      }

       … …

      template<typename R, typename T1, typename T2, typename T3, typename T4,
               typename T5, typename T6, typename T7, typename T8, typename T9,
               typename T10>
      inline void
      add_if_trackable(R ()(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)) const
      {
      }

      std::vector<const trackable
>& bound_objects;
    };


class trackable {
private:
    static void signal_disconnected(void obj, void data);

    friend class detail::signal_base_impl;
    friend class detail::slot_base;
    void signal_connected(connection, signals::detail::bound_object&) const;

protected:
    trackable() : connected_signals(), dying(false) {}
    trackable(const trackable&) : connected_signals(), dying(false) {}
    ~trackable();

    trackable& operator=(const trackable&)
    {
      connected_signals.clear();
      return this;
    }

private:
    typedef std::list<connection> connection_list;
    typedef connection_list::iterator connection_iterator;


    mutable connection_list connected_signals;


    mutable bool dying;
};

    void trackable::signal_disconnected(void
obj, void data)
    {
      trackable
self = reinterpret_cast<trackable>(obj);
      connection_iterator
signal =
        reinterpret_cast<connection_iterator>(data);

      // If we’re dying, don’t bother erasing the connection from the list;
      // it’ll be gone anyway
      if (!self->dying) {
        self->connected_signals.erase(
signal);
      }

      // This iterator pointer won’t ever be used again
      delete signal;
    }

    void
    trackable::signal_connected(connection c,
                                BOOST_SIGNALS_NAMESPACE::detail::bound_object& binding) const
    {
      // Insert the connection
      connection_iterator pos =
        connected_signals.insert(connected_signals.end(), c);

      // Make this copy of the object disconnect when destroyed
      pos->set_controlling();

      binding.obj = const_cast<void>(reinterpret_cast<const void>(this));
      binding.data = reinterpret_cast<void>(new connection_iterator(pos));
      binding.disconnect = &signal_disconnected;
    }

    trackable::~trackable()
    {
      dying = true;
    }


      void slot_base::create_connection()
      {
        // Create a new connection object
        basic_connection
con = new basic_connection();

        / nothrow / {
          // The signal portion isn’t really necessary, except that we need a
          // signal for the connection to be connected.
          con->signal = static_cast<void>(this);
          con->signaldata = 0;
          con->blocked
= false ;
          con->signal_disconnect = &bound_object_destructed;
        }

        // This connection watches for destruction of bound objects. Note
        // that the reset routine will delete con if an allocation throws
        data->watch_bound_objects.reset(con);

        // We create a scoped connection, so that exceptions thrown while
        // adding bound objects will cause a cleanup of the bound objects
        // already connected.
        scoped_connection safe_connection(data->watch_bound_objects);

        // Now notify each of the bound objects that they are connected to this
        // slot.
        for(std::vector<const trackable
>::iterator i =
              data->bound_objects.begin();
            i != data->bound_objects.end(); ++i) {
          // Notify the object that the slot is connecting to it
          BOOST_SIGNALS_NAMESPACE::detail::bound_object binding;
          (i)->signal_connected(data->watch_bound_objects, binding);

          // This will notify the bound object that the connection just made
          // should be disconnected if an exception is thrown before the
          // end of this iteration
          BOOST_SIGNALS_NAMESPACE::detail::auto_disconnect_bound_object
            disconnector(binding);

          // Add the binding to the list of bindings for the connection
          con->bound_objects.push_back(binding);

          // The connection object now knows about the bound object, so if an
          // exception is thrown later the connection object will notify the
          // bound object of the disconnection automatically
          disconnector.release();
        }

        // No exceptions will be thrown past this point.
        safe_connection.release();

        data->watch_bound_objects.set_controlling(true);
      }


      struct basic_connection {
        void
signal;
        void signal_data;
        void (
signaldisconnect)(void, void);
        bool blocked
;

        std::list<bound_object> bound_objects;
      };


    class connection :
      private less_than_comparable1<connection>,
      private equality_comparable1<connection>
    {
    public:
      connection() : con(), controlling_connection(false) {}
      connection(const connection&);
      ~connection();



      void block(bool shouldblock = true) { con->blocked = shouldblock; }
      void unblock() { con->blocked
= false; }
      bool blocked() const { return !connected() || con->blocked_; }


      void disconnect() const;


      bool connected() const { return con.get() && con->signal_disconnect; }


      bool operator==(const connection& other) const;
      bool operator<(const connection& other) const;


      connection& operator=(const connection& other) ;


      void swap(connection& other);

    public:

      void set_controlling(bool control = true)
      { controlling_connection = control; }

      shared_ptr<signals::detail::basic_connection>
      get_connection() const
      { return con; }

    private:
      friend class detail::signal_base_impl;
      friend class detail::slot_base;
      friend class trackable;


      void reset(signals::detail::basic_connection);


      void add_bound_object(const signals::detail::bound_object& b);

      friend class signals::detail::bound_objects_visitor;


      shared_ptr<signals::detail::basic_connection> con;


      bool controlling_connection;
    };

    void connection::disconnect() const
    {
      if (this->connected()) {
        // Make sure we have a reference to the basic_connection object,
        // because ‘this’ may disappear
        shared_ptr<detail::basic_connection> local_con = con;

        void (
signal_disconnect)(void, void) = local_con->signal_disconnect;

        // Note that this connection no longer exists
        // Order is important here: we could get into an infinite loop if this
        // isn’t cleared before we try the disconnect.
        local_con->signal_disconnect = 0;

        // Disconnect signal
        signal_disconnect(local_con->signal, local_con->signal_data);

        // Disconnect all bound objects
        typedef std::list<BOOST_SIGNALS_NAMESPACE::detail::bound_object>::iterator iterator;
        for (iterator i = local_con->bound_objects.begin();
             i != local_con->bound_objects.end(); ++i) {
          assert(i->disconnect != 0);
          i->disconnect(i->obj, i->data);
        }
      }
    }