Error

C++博客 首页 新随笔 联系 聚合 管理
  217 Posts :: 61 Stories :: 32 Comments :: 0 Trackbacks
// boost_singal_solt.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <boost/signals2.hpp>
class CTarget /*: public boost::signals2::trackable*/
{
public:
    virtual ~CTarget()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
    CTarget()
    {
        m_strMsg = "1343rwkjdfkjdfasdklf";
    }
    void SomeHandle()
    {
        std::cout << __FUNCTION__ << std::endl;
        std::cout << m_strMsg << std::endl;
    }
    void SomeHandle1()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
private:
    std::string m_strMsg;
};
class CSource
{
public:
    boost::signals2::connection Connect(const boost::signals2::signal<void(void)>::slot_type &sub)
    {
        return m_sig.connect(sub);
    }
    void OnSig()
    {
        m_sig();
    }
private:
    boost::signals2::signal<void(void)> m_sig;
};
int _tmain(int argc, _TCHAR* argv[])
{
    CSource source;
    boost::signals2::connection conn;
    {
        CTarget target;
        
        /*conn = */source.Connect(boost::bind(&CTarget::SomeHandle, &target));
        source.Connect(boost::bind(&CTarget::SomeHandle1, &target));
        source.OnSig();
    }
    source.OnSig();
return 0;
}


在继承boost::signals2::trackable的情况下,Target析构以后不会调用,但是不继承是会调用的。也就是说,这是一个危险操作,不知道内部怎么管理的,会不会出现内存泄漏?
/////////////////////////////////////////////////////////////////////////////


// boost_singal_solt.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <boost/signals2.hpp>
class CSource
{
public:
    boost::signals2::connection Connect(const boost::signals2::signal<void(void)>::slot_type &sub)
    {
        return m_sig.connect(sub);
    }
    void OnSig()
    {
        m_sig();
    }
private:
    boost::signals2::signal<void(void)> m_sig;
};
class CTarget : public boost::signals2::trackable
{
public:
    virtual ~CTarget()
    {
        std::cout << __FUNCTION__ << std::endl;
        m_con.disconnect();
    }
    CTarget()
    {
        m_strMsg = "1343rwkjdfkjdfasdklf";
    }
    void RegisterSolts(CSource& source)
    {
        m_con = source.Connect(boost::bind(&CTarget::SomeHandle, this));
    }
    void SomeHandle()
    {
        std::cout << __FUNCTION__ << std::endl;
        std::cout << m_strMsg << std::endl;
    }
    void SomeHandle1()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
private:
    std::string m_strMsg;
    boost::signals2::connection m_con;
};
int _tmain(int argc, _TCHAR* argv[])
{
    CSource source;
    boost::signals2::connection conn;
    {
        CTarget target;
        
        target.RegisterSolts(source);
        //source.OnSig();
    }
    source.OnSig();
return 0;
}
确认只要维护好connection在对象target析构以后一定是disconnect应该就OK没事,,,





///////////////////////////////////////////


整体上看来是这样:
问题:target的成员函数和this指针打包注册到source上以后,如果target析构,source无法感知到,可能会调用已经成为野指针的target地址。
解决:signals2库的解决办法是,用一个connection来维护打包的target成员函数和source上的signal的连接关系。target持有这个connection,当自身析构的时候必须调用disscontion解除这个关系。

如果要抄袭,也是要设计一种机制,在target析构的时候,想办法清除它在别处注册的函数指针。
1.可以建立target到source的关系,target析构以后通知source,souce清理自身保留的target相关打包函数。这种方式在使用boost bind的时候可能就有问题了,应为之依靠target指针去判断bind出来的function有难度。
2.建立关系的时候就将解除关系的函数打包到一个新的对象中,然后由target负责在自己析构的时候去调用它。

!!!如果source先于target析构,就悲剧了。但是实际情况是,如果source已经析构了,也无法触发target绑定的函数了。但问题是,target析构的时候还是去触发source绑定到target的解除关系的函数。悲催。但是实际测试这个问题不存在,估计是用类似weak_ptr的技术。
在完全理解之前,务必保证source生命周期大于target
// boost_singal_solt.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <boost/signals2.hpp>
class CSource
{
public:
    boost::signals2::connection Connect(const boost::signals2::signal<void(void)>::slot_type &sub)
    {
        return m_sig.connect(sub);
    }
    void OnSig()
    {
        m_sig();
    }
private:
    boost::signals2::signal<void(void)> m_sig;
};
class CTarget : public boost::signals2::trackable
{
public:
    virtual ~CTarget()
    {
        //std::cout << __FUNCTION__ << std::endl;
        m_con.disconnect();
    }
    CTarget()
    {
        m_strMsg = "1343rwkjdfkjdfasdklf";
    }
    void RegisterSolts(CSource& source)
    {
        m_con = source.Connect(boost::bind(&CTarget::SomeHandle, this));
    }
    void SomeHandle()
    {
        std::cout << __FUNCTION__ << std::endl;
        std::cout << m_strMsg << std::endl;
    }
    void SomeHandle1()
    {
        std::cout << __FUNCTION__ << std::endl;
    }
private:
    std::string m_strMsg;
    boost::signals2::connection m_con;
};
int _tmain(int argc, _TCHAR* argv[])
{
    for (;;)
    {
        CSource* pSource = new CSource;
        boost::signals2::connection conn;
        CTarget* pTarget = new CTarget;
        pTarget->RegisterSolts(*pSource);
        delete pSource;
        delete pTarget;
    }
    //source.OnSig();
return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

没有完全读明白之前,在需要7×24运行的环境还是慎重使用。不过客户端貌似无所谓,,,囧。
posted on 2014-05-30 01:09 Enic 阅读(776) 评论(0)  编辑 收藏 引用 所属分类: boost

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理