webrtc(1) 信號槽sigslot

信號槽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;
	};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章