信号槽sigslot
信号槽的作用
webrtc中有一个重要基础组件——信号槽,它和qt中的信号槽类似,它以发送信号的方式分离调用者和被调用者,达到耦合的目的。另外,webrtc中的信号槽是线程安全的。
信号槽的用法
#include "sigslot.h"
#include <string>
using namespace std;
using namespace sigslot;
// 信号发送者
class MessageSender {
public:
void sendMsg() {
string id = "000001";
string name = "jack";
msg_sig(id, name);
}
public:
// 定义一个包含两个参数的信号
sigslot::signal2<string, string> msg_sig;
};
// 信号接收者,需要继承sigslot::has_slots<>
class MessageReceiver:public sigslot::has_slots<>{
public:
// 处理信号
void receiveMsg(string id,string name) {
fprintf(stderr, "id=%s,name=%s\n", id.c_str(), name.c_str());
}
};
int main()
{
MessageSender sender;
MessageReceiver receiver;
// 绑定信号和槽
sender.msg_sig.connect(&receiver, &MessageReceiver::receiveMsg);
// 发送消息
for (int i = 0; i < 1024; ++i) {
sender.sendMsg();
}
return 0;
}
信号槽的用法如下:
1、定义信号
sigslot::signal2<string, string> msg_sig;
2、定义槽
class MessageReceiver:public sigslot::has_slots<>{
public:
// 处理信号
void receiveMsg(string id,string name) {
fprintf(stderr, "id=%s,name=%s\n", id.c_str(), name.c_str());
}
};
3、把信号和槽连接起来
sender.msg_sig.connect(&receiver, &MessageReceiver::receiveMsg);
4、发送信号
sender.sendMsg();
信号槽的组成
信号槽有三个部分:
1、信号
signal0,signal1,signal2...都是信号类,它们的实现基本一样,仅参数的数量不同
template<class arg1_type, class arg2_type, class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
class signal2 : public _signal_base2<arg1_type, arg2_type, mt_policy>
{
public:
typedef _signal_base2<arg1_type, arg2_type, mt_policy> base;
typedef typename base::connections_list connections_list;
using base::m_connected_slots;
signal2()
{
;
}
signal2(const signal2<arg1_type, arg2_type, mt_policy>& s)
: _signal_base2<arg1_type, arg2_type, mt_policy>(s)
{
;
}
// 把信号和槽连接在一起,实际上是通过_connection2进行连接的
template<class desttype>
void connect(desttype* pclass, void (desttype::*pmemfun)(arg1_type,
arg2_type))
{
// 加锁(单线程的时候锁函数是空的)
lock_block<mt_policy> lock(this);
// 创建连接器(管道),参数分包是信号 和 槽
_connection2<desttype, arg1_type, arg2_type, mt_policy>* conn = new
_connection2<desttype, arg1_type, arg2_type, mt_policy>(pclass, pmemfun);
m_connected_slots.push_back(conn);
pclass->signal_connect(this);
}
// 发射信号(即触发消息发送,实质就是进行函数调用)
void emit(arg1_type a1, arg2_type a2)
{
lock_block<mt_policy> lock(this);
typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
typename connections_list::const_iterator itEnd = m_connected_slots.end();
while(it != itEnd)
{
itNext = it;
++itNext;
(*it)->emit(a1, a2);
it = itNext;
}
}
// 和emit一样
void operator()(arg1_type a1, arg2_type a2)
{
lock_block<mt_policy> lock(this);
typename connections_list::const_iterator itNext, it = m_connected_slots.begin();
typename connections_list::const_iterator itEnd = m_connected_slots.end();
while(it != itEnd)
{
itNext = it;
++itNext;
(*it)->emit(a1, a2);
it = itNext;
}
}
};
2、连接器(管道)
_connection0,_connection1,_connection2...都是连接器(管道)类,它们的实现都是一样的,仅参数的数量不同
template<class dest_type, class arg1_type, class arg2_type, class mt_policy>
class _connection2 : public _connection_base2<arg1_type, arg2_type, mt_policy>
{
public:
_connection2()
{
m_pobject = NULL;
m_pmemfun = NULL;
}
_connection2(dest_type* pobject, void (dest_type::*pmemfun)(arg1_type,
arg2_type))
{
m_pobject = pobject;
m_pmemfun = pmemfun;
}
virtual ~_connection2()
{
}
virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone()
{
return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>(*this);
}
virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots_interface* pnewdest)
{
return new _connection2<dest_type, arg1_type, arg2_type, mt_policy>((dest_type *)pnewdest, m_pmemfun);
}
// 触发消息响应
virtual void emit(arg1_type a1, arg2_type a2)
{
(m_pobject->*m_pmemfun)(a1, a2);
}
virtual has_slots_interface* getdest() const
{
return m_pobject;
}
private:
dest_type* m_pobject;
void (dest_type::* m_pmemfun)(arg1_type, arg2_type);
};
3、槽
/*
** 槽
*/
template<class mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
class has_slots : public has_slots_interface, public mt_policy
{
private:
typedef std::set<_signal_base_interface*> sender_set; // 多个消息可以发送到一个槽
typedef sender_set::const_iterator const_iterator;
public:
has_slots()
{
;
}
has_slots(const has_slots& hs)
{
lock_block<mt_policy> lock(this);
const_iterator it = hs.m_senders.begin();
const_iterator itEnd = hs.m_senders.end();
while(it != itEnd)
{
(*it)->slot_duplicate(&hs, this);
m_senders.insert(*it);
++it;
}
}
// 把某个信号和当前的槽连接在一起
void signal_connect(_signal_base_interface* sender)
{
lock_block<mt_policy> lock(this);
m_senders.insert(sender);
}
// 断开信号和槽的连接
void signal_disconnect(_signal_base_interface* sender)
{
lock_block<mt_policy> lock(this);
m_senders.erase(sender);
}
virtual ~has_slots()
{
disconnect_all();
}
void disconnect_all()
{
lock_block<mt_policy> lock(this);
const_iterator it = m_senders.begin();
const_iterator itEnd = m_senders.end();
while(it != itEnd)
{
(*it)->slot_disconnect(this);
++it;
}
m_senders.erase(m_senders.begin(), m_senders.end());
}
private:
sender_set m_senders;
};