// boost_singal_solt.cpp : Defines the entry point for the console application.
boost::signals2::connection Connect(const boost::signals2::signal<void(void)>::slot_type &sub)
在繼承boost::signals2::trackable的情況下,Target析構(gòu)以后不會(huì)調(diào)用,但是不繼承是會(huì)調(diào)用的。也就是說(shuō),這是一個(gè)危險(xiǎn)操作,不知道內(nèi)部怎么管理的,會(huì)不會(huì)出現(xiàn)內(nèi)存泄漏?
/////////////////////////////////////////////////////////////////////////////
// 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;
}
確認(rèn)只要維護(hù)好connection在對(duì)象target析構(gòu)以后一定是disconnect應(yīng)該就OK沒(méi)事,,,
///////////////////////////////////////////
整體上看來(lái)是這樣:
問(wèn)題:target的成員函數(shù)和this指針打包注冊(cè)到source上以后,如果target析構(gòu),source無(wú)法感知到,可能會(huì)調(diào)用已經(jīng)成為野指針的target地址。
解決:signals2庫(kù)的解決辦法是,用一個(gè)connection來(lái)維護(hù)打包的target成員函數(shù)和source上的signal的連接關(guān)系。target持有這個(gè)connection,當(dāng)自身析構(gòu)的時(shí)候必須調(diào)用disscontion解除這個(gè)關(guān)系。
如果要抄襲,也是要設(shè)計(jì)一種機(jī)制,在target析構(gòu)的時(shí)候,想辦法清除它在別處注冊(cè)的函數(shù)指針。
1.可以建立target到source的關(guān)系,target析構(gòu)以后通知source,souce清理自身保留的target相關(guān)打包函數(shù)。這種方式在使用boost bind的時(shí)候可能就有問(wèn)題了,應(yīng)為之依靠target指針去判斷bind出來(lái)的function有難度。
2.建立關(guān)系的時(shí)候就將解除關(guān)系的函數(shù)打包到一個(gè)新的對(duì)象中,然后由target負(fù)責(zé)在自己析構(gòu)的時(shí)候去調(diào)用它。
!!!如果source先于target析構(gòu),就悲劇了。但是實(shí)際情況是,如果source已經(jīng)析構(gòu)了,也無(wú)法觸發(fā)target綁定的函數(shù)了。但問(wèn)題是,target析構(gòu)的時(shí)候還是去觸發(fā)source綁定到target的解除關(guān)系的函數(shù)。悲催。但是實(shí)際測(cè)試這個(gè)問(wèn)題不存在,估計(jì)是用類(lèi)似weak_ptr的技術(shù)。
在完全理解之前,務(wù)必保證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;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
沒(méi)有完全讀明白之前,在需要7×24運(yùn)行的環(huán)境還是慎重使用。不過(guò)客戶(hù)端貌似無(wú)所謂,,,囧。