boost--signal--slot笔记

Boost库可谓博大精深,很多思想都很前卫或者说奇特,至少在我们实际的应用软件开发中,很少能够用到其中的思想,大部分也就是简单的类库调用,仅此而已。

大致上看了一下signal的实现,感觉里面的东西确实很复杂,为了以后更清晰的了解,运用,提高自己的技术水平,针对signal中的slot相关部分进行代码剖析,以备后用。

 

实例代码:

#include "stdafx.h"

#include "boost/signal.hpp"

#include "boost/bind.hpp"

#include "boost/ref.hpp"

#include <iostream>

using namespace std;

struct s1 : boost::signals::trackable

{

};

struct s2 : boost::signals::trackable

{

};

void Test_one(s1& test1, s2& test2)

{

    cout <<"This is my first look up the signal" <<endl;

}

int _tmain(int argc, _TCHAR* argv[])

{

    s1 t1;

    s2 t2;

    boost::signal<void(s1, s2) > sig;

    sig.connect(boost::bind(&Test_one, boost::ref(t1), boost::ref(t2)));

 

    return 0;

}

 

以上代码中,当执行到sig.connect时,背后的强大引擎便被开启:

signal::connect(const slot_type& in_slot,

             BOOST_SIGNALS_NAMESPACE::connect_position at)

由于connect需要一个slot类型(slot_typesignal中的一个typedef,原类型即为slot,这时,面对一函数对象,便进行了一次类型转换,于是开始了本篇内容的赘述:

                    C:/Documents and Settings/Administrator/桌面/signals analyze/1.jpg

      图一 Slot类图

 

 

Slot的构造函数:

 

slot(const F& f) : slot_function(BOOST_SIGNALS_NAMESPACE::get_invocable_slot(f, BOOST_SIGNALS_NAMESPACE::tag_type(f)))

    {

      this->data.reset(new data_t);

 

      BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor

        do_bind(this->data->bound_objects);

      visit_each(do_bind,

                 BOOST_SIGNALS_NAMESPACE::get_inspectable_slot

                   (f, BOOST_SIGNALS_NAMESPACE::tag_type(f)));

      create_connection();

}

 

//这里,构造了一个dat_t对象见图一,用来记录trackable对象,以及记录一个connection对象的副本,具体如何被记录的,请慢慢往下看。

首先,visit_each会将bind对象中的可跟踪对象包括参数(即继承自trackable类)收集起来,放在了data结构中的bound_objects。具体它是怎么获得,可以根据实例代码调试追踪即可看到源码的实现。于是,bound_objects中记录了s1s2所对应的对象的指针。要干什么用,见后文分析。

再后来,重量级的函数 create_connection函数出场了。

create_connection();

不看源码,先猜猜它要干什么,应该是建立一个连接,记录一些信息,以备后用。果真如此吗?

 

 

 

 

                    图二 connection类结构

 

 

代码片段一:

      void slot_base::create_connection()

      {

         basic_connection* con = new basic_connection();

 

          con->signal = static_cast<void*>(this);

          con->signal_data = 0;

          con->blocked_ = false ;

          con->signal_disconnect = &bound_object_destructed;

 

data->watch_bound_objects.reset(con);

 

这里先new了一个连接,设置其成员,并设置slot成员变量 data->watch_bound_objects保存该con

 

                        图三 trackable类结构

 

 

代码片段二(参考图二和图三)

scoped_connection safe_connection(data->watch_bound_objects);

       for(std::vector<const trackable*>::iterator i =

              data->bound_objects.begin();

            i != data->bound_objects.end(); ++i) {

        

          BOOST_SIGNALS_NAMESPACE::detail::bound_object binding;

          (*i)->signal_connected(data->watch_bound_objects, binding);

         

 

          con->bound_objects.push_back(binding);

 

 

遍历data->bound_objects(见图一),然后就追溯到trackablesignal_coonected函数中了

    void trackable::signal_connected(connection c,

                               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));//trackable对象

      binding.data = reinterpret_cast<void*>(new connection_iterator(pos));

      binding.disconnect = &signal_disconnected;

}

 

这里其实是为了解决某一个trackable对象同时被多个signal记录并进行追踪的情况。该函数作了两个工作,1)将连接记录到trackable中,2)填充bound_object对象,该对象被记录在了新建的连接con中。

 

综上所述:

可以看到,trackable中记录了该次连接,如果trackable对象被析构了,那么可以找到该连接,并将其断开。

 

详细的内容大家可以参考一下:http//bolg.csdn.net/pongba好多内容分析的很是经典。

你可能感兴趣的:(object,basic,iterator,each,Signal,binding)