// 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运行的环境还是慎重使用。不过客户端貌似无所谓,,,囧。