webrtc的signal slot实现分析
程序员文章站
2022-07-01 15:36:55
...
sigslot.h
#ifndef RTC_BASE_THIRD_PARTY_SIGSLOT_SIGSLOT_H_
#define RTC_BASE_THIRD_PARTY_SIGSLOT_SIGSLOT_H_
#include <stdlib.h>
#include <cstring>
#include <list>
#include <set>
#include <pthread.h>
#include <iostream>
#ifndef SIGSLOT_DEFAULT_MT_POLICY
#ifdef _SIGSLOT_SINGLE_THREADED
#define SIGSLOT_DEFAULT_MT_POLICY single_threaded
#else
#define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
#endif
#endif
// TODO: change this namespace to rtc?
namespace sigslot {
/**< 单线程*/
class single_threaded {
public:
void lock() {} ///< 上锁
void unlock() {} ///< 解锁
};
// The multi threading policies only get compiled in if they are enabled.
/**< 多线程(全局)*/
class multi_threaded_global {
public:
void lock() { pthread_mutex_lock(get_mutex()); } ///< 上锁
void unlock() { pthread_mutex_unlock(get_mutex()); } ///< 解锁
private:
static pthread_mutex_t* get_mutex(); ///< 获取锁的私有静态方法,在sigslot.cpp中实现
};
/**< 多线程(本地)*/
class multi_threaded_local {
public:
multi_threaded_local() { pthread_mutex_init(&m_mutex, nullptr); }
multi_threaded_local(const multi_threaded_local&) {
pthread_mutex_init(&m_mutex, nullptr);
}
~multi_threaded_local() { pthread_mutex_destroy(&m_mutex); }
void lock() { pthread_mutex_lock(&m_mutex); }
void unlock() { pthread_mutex_unlock(&m_mutex); }
private:
pthread_mutex_t m_mutex;
};
///< template class lock_block
/**< 锁块(临界区):将锁块所处的线程环境进行泛化(模板), 以适应多种线程环境 */
template <class mt_policy>
class lock_block {
public:
mt_policy* m_mutex; ///< 在<mt_policy>线程环境下的锁
lock_block(mt_policy* mtx) : m_mutex(mtx) { m_mutex->lock(); } ///< ctor 上锁
~lock_block() { m_mutex->unlock(); } ///< dtor 解锁
};
class _signal_base_interface; ///< 前置声明 信号基类(接口类)
///< interface class: has_slots_interface
/**< has_slots 的槽接口类 */
class has_slots_interface {
private:
typedef void (*signal_connect_t)(has_slots_interface* self,
_signal_base_interface* sender);
typedef void (*signal_disconnect_t)(has_slots_interface* self,
_signal_base_interface* sender);
typedef void (*disconnect_all_t)(has_slots_interface* self);
///< private member variable: func pointer 私有的函数指针成员变量;
const signal_connect_t m_signal_connect; ///< 连接
const signal_disconnect_t m_signal_disconnect; ///< 断开连接
const disconnect_all_t m_disconnect_all; ///< 断开所有连接
protected:
///< ctor:初始化其指针成员变量;
has_slots_interface(signal_connect_t conn,
signal_disconnect_t disc,
disconnect_all_t disc_all)
: m_signal_connect(conn),
m_signal_disconnect(disc),
m_disconnect_all(disc_all) {}
// Doesn't really need to be virtual, but is for backwards compatibility
// (it was virtual in a previous version of sigslot).
///< virtual dtor
virtual ~has_slots_interface() {}
public:
/**< 公有方法:该槽 与 信号 连接 */
void signal_connect(_signal_base_interface* sender) {
///< 调用构造函数传递进来的conn函数指针,以此槽 has_slot_interface(this)和 信号_signal_base_interface(sender) 为参数
m_signal_connect(this, sender);
}
/**< 公有方法:该槽 与 信号 断开连接 */
void signal_disconnect(_signal_base_interface* sender) {
///< 调用构造函数传递进来的disc函数指针,以此槽 has_slot_interface(this)和 信号 _signal_base_interface(sender) 为参数
m_signal_disconnect(this, sender);
}
/**< 公有方法:该槽 与 所有信号 断开连接 */
void disconnect_all() {
///< 调用构造函数传递进来的disc_all函数指针,以此槽 has_slot_interface(this)和 信号 _signal_base_interface(sender) 为参数
m_disconnect_all(this);
}
};
///< base interface class: _signal_base_interface
///< 信号基类(接口类)
class _signal_base_interface {
private:
typedef void (*slot_disconnect_t)(_signal_base_interface* self,
has_slots_interface* pslot);
typedef void (*slot_duplicate_t)(_signal_base_interface* self,
const has_slots_interface* poldslot,
has_slots_interface* pnewslot);
///< private member variable: func pointer 私有的函数指针成员变量;
const slot_disconnect_t m_slot_disconnect; ///< 槽断开连接
const slot_duplicate_t m_slot_duplicate; ///< 槽复制
protected:
///< ctor 初始化其指针成员变量;
_signal_base_interface(slot_disconnect_t disc, slot_duplicate_t dupl)
: m_slot_disconnect(disc), m_slot_duplicate(dupl) {}
///< virtual dtor
~_signal_base_interface() {}
public:
/**< 公有方法:槽 与 该信号 断开连接 */
void slot_disconnect(has_slots_interface* pslot) {
///< 调用构造函数传递进来的disc函数指针,以 has_slot_interface(pslot)和 该信号_signal_base_interface(this) 为参数
m_slot_disconnect(this, pslot);
}
/**< 公有方法:该信号 复制槽 */
void slot_duplicate(const has_slots_interface* poldslot,
has_slots_interface* pnewslot) {
/**< 调用构造函数传递进来的disc函数指针,以 该信号_signal_base_interface(this) 和
* has_slot_interface(poldslot)
* 以及has_slot_interface(pnewslot)为参数
*/
m_slot_duplicate(this, poldslot, pnewslot);
}
};
/**< 不透明连接
* 根据构造函数传递进来的DestT类型(必然要是一个派生自has_slots_interface的类)
* 触发调用该DestT的成员函数
*/
class _opaque_connection {
private:
typedef void (*emit_t)(const _opaque_connection*);
///< 泛型联合,将 起始 和 到达 泛化
template <typename FromT, typename ToT>
union union_caster {
FromT from;
ToT to;
};
emit_t pemit; ///< 属性:function pointer
has_slots_interface* pdest; ///< 属性:槽 指针
// Pointers to member functions may be up to 16 bytes for virtual classes,
// so make sure we have enough space to store it.
/// 指向虚类的成员函数指针大小可能达到16字节,确保有足够的空间存储之;
/**< 摘自网络:类成员函数指针与普通函数指针不是一码事。前者要用.*与->*运算符来使用,
* 而后者可以用*运算符(称为“解引用”dereference,或称“间址”indirection)。
* 普通函数指针实际上保存的是函数体的开始地址,因此也称“代码指针”,以区别于C/C++最常用的数据指针。
* 而类成员函数指针就不仅仅是类成员函数的内存起始地址,还需要能解决因为C++的多重继承、
* 虚继承而带来的类实例地址的调整问题。因此,普通函数指针的尺寸就是普通指针的尺寸,
* 例如32位程序是4字节,64位程序是8字节。而类成员函数指针的尺寸最多有4种可能:
* 1. 单倍指针尺寸:对于非派生类、单继承类,类成员函数指针保存的就是成员函数的内存起始地址。
* 2. 双倍指针尺寸:对于多重继承类,类成员函数指针保存的是成员函数的内存起始地址与this指针调整值。
因为对于多继承类的类成员函数指针,可能对应于该类自身的成员函数,或者最左基类的成员函数,
这两种情形都不需要调整this指针。如果类成员函数指针保存的其他的非最左基类的成员函数的地址,
根据C++标准,非最左基类实例的开始地址与派生类实例的开始地址肯定不同,所以需要调整this指针,使其指向非最左基类实例。
* 3. 三倍指针尺寸:对于多重继承且虚继承的类。类成员函数指针保存的就是成员函数的内存起始地址、this指针调整值、
虚基类调整值在虚基表(vbtable)中的位置共计3项。以常见的“菱形虚继承”为例。最派生类多重继承了两个类,
称为左父类、右父类;两个父类共享继承了一个虚基类。最派生类的成员函数指针可能保存了这四个类的成员函数的内存地址。
如果成员函数指针保存了最派生类或左父类的成员函数地址,则最为简单,不需要调整this指针值。
如果如果成员函数指针保存了右父类的成员函数地址,则this指针值要加上一个偏移值,指向右父类实例的地址。
如果成员函数指针保存了虚基类的成员函数地址,由于C++类继承的复杂多态性质,必须到最派生类虚基表的相应条目
查出虚基类地址的偏移值,依此来调整this指针指向虚基类。
* 4. 四倍指针尺寸:C++标准允许一个仅仅是声明但没有定义的类(forward declaration)的成员函数指针,
可以被定义、被调用。这种情况下,实际上对该类一无所知。这称作未知类型(unknown)的成员函数指针。
该类的成员函数指针需要留出4项数据位置,分别用于保存成员函数的内存起始地址、this指针调整值、
虚基表到类的开始地址的偏移值(vtordisp)、虚基类调整值在虚基表(vbtable)中的位置,共计4项。
*/
unsigned char pmethod[16];
public:
/**< 模板构造函数:_opaque_connection, 将目标类型(DestT) 和 目标类型::成员函数参数(Args...) 泛化
* 这里的变参模板特性同时达到 参数类型泛化 和 参数个数泛化 的目的,C++11棒棒哒!
*/
template <typename DestT, typename... Args>
_opaque_connection(DestT* pd, void (DestT::*pm)(Args...)) : pdest(pd) {
std::cout << "333. " << "_opaque_connection(DestT* pd, void (DestT::*pm)(Args...))" << std::endl;
typedef void (DestT::*pm_t)(Args...); ///< pm_t 成员函数指针类型
static_assert(sizeof(pm_t) <= sizeof(pmethod),
"Size of slot function pointer too large.");
///< 成员函数指针拷贝
/**< 成员函数指针:
1、函数指针赋值要使用 &
2、使用 .* (实例对象)或者 ->*(实例对象指针)调用类成员函数指针所指向的函数
*/
std::cout << "444. " << "std::memcpy(pmethod, &pm, sizeof(pm_t)): pmethod 保存成员函数指针" << std::endl;
std::memcpy(pmethod, &pm, sizeof(pm_t)); /// pmethod 保存成员函数指针
typedef void (*em_t)(const _opaque_connection* self, Args...);
///< 前面定义的 typedef void (*emit_t)(const _opaque_connection*);
///< 具体化泛型 <FromT, ToT> ==>造型 <em_t, emit_t>
union_caster<em_t, emit_t> caster2; ///< 造型得到 union_caster <em_t, emit_t> 类型的 实例 caster2
/**< 初始化em_t(成员函数指针void (DestT::*pm_t)(Args...))类型的变量 from
* 此处将from其初始为指向 _opaque_connection::emitter<DestT, Args...> 成员函数指针;
*/
caster2.from = &_opaque_connection::emitter<DestT, Args...>; ///< 成员函数指针赋值要使用 &
/**< 普通的函数指针,私有成员 pemit 赋值为 caster2.to (emit_t函数指针类型)???caster2.to 在何处初始化的
* Oh!这是联合哎,亲~~~~~~~~~,这两个联合成员都是普通的function pointer,故而你懂得!
*/
pemit = caster2.to; ///< aka. caster2.from ==> aka. _opaque_connection::emitter<DestT, Args...>
}
has_slots_interface* getdest() const { return pdest; } ///< 获取槽指针 pdest
/**< 复制方法 传入新的槽指针newtarget */
_opaque_connection duplicate(has_slots_interface* newtarget) const {
_opaque_connection res = *this;
res.pdest = newtarget; ///< 槽指针 pdest 赋值为 newtarget
return res;
}
// Just calls the stored "emitter" function pointer stored at construction
// time. 调用在构造函数调用时传递来的 “emitter” 函数指针 _opaque_connection::emitter<DestT, Args...>
///< 变参函数模板
template <typename... Args>
void emit(Args... args) const {
std::cout << "999. _opaque_connection::emit(Args... args)" << std::endl;
typedef void (*em_t)(const _opaque_connection*, Args...);
///< 前面定义的 typedef void (*emit_t)(const _opaque_connection*);
///< 具体化泛型 <FromT, ToT> ==>造型 <emit_t, em_t>
union_caster<emit_t, em_t> caster;
caster.from = pemit; ///< pemit 在ctor中被初始化为 caster2.to, aka. _opaque_connection::emitter<DestT, Args...>
(caster.to)(this, args...); ///< 调用 caster.to, aka. _opaque_connection::emitter<DestT, Args...>
}
private:
///< 静态成员函数(模板)
template <typename DestT, typename... Args>
static void emitter(const _opaque_connection* self, Args... args) {
std::cout << "aaa. static void _opaque_connection::emitter(const _opaque_connection* self, Args... args)" << std::endl;
typedef void (DestT::*pm_t)(Args...);
pm_t pm;
std::memcpy(&pm, self->pmethod, sizeof(pm_t)); ///< 成员函数指针拷贝到pm_t
/**< has_slots_interface* pdest 在构造函数中初始化
* 再将其转为<DestT*> 类型,然后访问 pm 指向的成员函数
*/
std::cout << "bbb. has_slots_interface* pdest 在构造函数中初始化 再将其转为<DestT*> 类型,然后访问 pm 指向的成员函数" << std::endl;
std::cout << "(static_cast<DestT*>(self->pdest)->*(pm))(args...)" << std::endl;
(static_cast<DestT*>(self->pdest)->*(pm))(args...);
}
};
///< 线程策略进行泛化 ,信号基类
template <class mt_policy>
class _signal_base : public _signal_base_interface, public mt_policy { ///< 从 信号基类(接口类),和 多线程策略 派生而来
protected:
typedef std::list<_opaque_connection> connections_list; ///< 不透明连接表
/**< ctor , 调用基类的ctor,
* 传入this派生类 _signal_base的 do_slot_disconnect, do_slot_duplicate 成员函数指针
*/
_signal_base()
: _signal_base_interface(&_signal_base::do_slot_disconnect,
&_signal_base::do_slot_duplicate),
m_current_iterator(m_connected_slots.end()) {}
~_signal_base() { disconnect_all(); }
private:
_signal_base& operator=(_signal_base const& that); ///< 不允许拷贝赋值操作
public:
/**< ctor , 调用基类的ctor,
* 传入this派生类 _signal_base的 do_slot_disconnect, do_slot_duplicate 成员函数指针
*/
_signal_base(const _signal_base& o)
: _signal_base_interface(&_signal_base::do_slot_disconnect,
&_signal_base::do_slot_duplicate),
m_current_iterator(m_connected_slots.end()) {
lock_block<mt_policy> lock(this);
for (const auto& connection : o.m_connected_slots) { ///< 遍历所有的o的m_connected_slots(_opaque_connection类型)列表
///< 获取槽指针(has_slots_interface*),调用 has_slots_interface 的 signal_connect 方法,
///< 将该槽(_opaque_connection 类型的connection)与信号(this表征)连接
connection.getdest()->signal_connect(this);
m_connected_slots.push_back(connection); ///< 同时将该槽 放置到信号this的已连接槽列表上;
}
}
bool is_empty() {
lock_block<mt_policy> lock(this); ///< critical zone
return m_connected_slots.empty();
}
void disconnect_all() {
lock_block<mt_policy> lock(this); ///< critical zone
while (!m_connected_slots.empty()) {
///< 获取槽指针(has_slots_interface*)
has_slots_interface* pdest = m_connected_slots.front().getdest();
m_connected_slots.pop_front();
///< 调用 has_slots_interface 的 signal_disconnect 方法
pdest->signal_disconnect(static_cast<_signal_base_interface*>(this)); ///< 打回原型
}
// If disconnect_all is called while the signal is firing, advance the
// current slot iterator to the end to avoid an invalidated iterator from
// being dereferenced.
m_current_iterator = m_connected_slots.end();
}
#if !defined(NDEBUG)
bool connected(has_slots_interface* pclass) {
lock_block<mt_policy> lock(this); ///< critical zone
connections_list::const_iterator it = m_connected_slots.begin();
connections_list::const_iterator itEnd = m_connected_slots.end();
while (it != itEnd) {
if (it->getdest() == pclass) /// 槽(pclass 表征) 有没有和该信号连接
return true;
++it;
}
return false;
}
#endif
///< 槽(pclass 表征) 和该信号断开连接
void disconnect(has_slots_interface* pclass) {
lock_block<mt_policy> lock(this);
connections_list::iterator it = m_connected_slots.begin();
connections_list::iterator itEnd = m_connected_slots.end();
while (it != itEnd) {
if (it->getdest() == pclass) {
// If we're currently using this iterator because the signal is firing,
// advance it to avoid it being invalidated.
if (m_current_iterator == it) {
m_current_iterator = m_connected_slots.erase(it);
} else {
m_connected_slots.erase(it);
}
///< 调用 has_slots_interface 的 signal_disconnect 方法
pclass->signal_disconnect(static_cast<_signal_base_interface*>(this)); ///< this打回原型
return;
}
++it;
}
}
private:
///< 静态成员函数,断开信号p中指定的槽pslot
static void do_slot_disconnect(_signal_base_interface* p,
has_slots_interface* pslot) {
_signal_base* const self = static_cast<_signal_base*>(p); /// 具体化信号
lock_block<mt_policy> lock(self);
connections_list::iterator it = self->m_connected_slots.begin();
connections_list::iterator itEnd = self->m_connected_slots.end();
while (it != itEnd) { ///< 遍历m_connected_slots 不透明连接 列表
connections_list::iterator itNext = it;
++itNext;
if (it->getdest() == pslot) { ///< 如果不透明连接表里面的某槽,和pslot表征的槽相同
// If we're currently using this iterator because the signal is firing,
// advance it to avoid it being invalidated.
if (self->m_current_iterator == it) {
self->m_current_iterator = self->m_connected_slots.erase(it);
} else {
self->m_connected_slots.erase(it);
}
}
it = itNext;
}
}
///< 静态成员函数,将信号p中指定的槽oldtarget用槽newtarget覆盖,类似于拷贝赋值
static void do_slot_duplicate(_signal_base_interface* p,
const has_slots_interface* oldtarget,
has_slots_interface* newtarget) {
_signal_base* const self = static_cast<_signal_base*>(p);
lock_block<mt_policy> lock(self);
connections_list::iterator it = self->m_connected_slots.begin();
connections_list::iterator itEnd = self->m_connected_slots.end();
while (it != itEnd) {
if (it->getdest() == oldtarget) {
self->m_connected_slots.push_back(it->duplicate(newtarget)); ///< 传入新的槽指针newtarget
}
++it;
}
}
protected:
connections_list m_connected_slots; ///< 不透明连接 列表
// Used to handle a slot being disconnected while a signal is
// firing (iterating m_connected_slots).
connections_list::iterator m_current_iterator;
bool m_erase_current_iterator = false;
};
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; ///< 信号(sender)集合
typedef sender_set::const_iterator const_iterator;
public:
///< ctor
has_slots()
: has_slots_interface(&has_slots::do_signal_connect, ///< 用 has_slot 静态成员函数 初始化基类
&has_slots::do_signal_disconnect,
&has_slots::do_disconnect_all) {}
///< ctor 类似于拷贝构造
has_slots(has_slots const& o)
: has_slots_interface(&has_slots::do_signal_connect,
&has_slots::do_signal_disconnect,
&has_slots::do_disconnect_all) {
lock_block<mt_policy> lock(this);
for (auto* sender : o.m_senders) {
///< 对 原来o的m_sender 的每个信号,调用slot_duplicate方法,复制到this中
sender->slot_duplicate(&o, this);
m_senders.insert(sender); ///< 同时该sender放入this的m_sender集合中
}
}
~has_slots() { this->disconnect_all(); }
private:
has_slots& operator=(has_slots const&); ///< 不允许拷贝赋值操作
///< 静态成员函数,连接slot 和 signal
static void do_signal_connect(has_slots_interface* p,
_signal_base_interface* sender) {
std::cout << "555. static void has_slots<>::do_signal_connect(has_slots_interface* p,_signal_base_interface* sender)" << std::endl;
has_slots* const self = static_cast<has_slots*>(p);
lock_block<mt_policy> lock(self);
std::cout << "将此signal插入slot的signal集合中: self->m_senders.insert(sender)" << std::endl;
self->m_senders.insert(sender); ///< 将此signal插入slot的signal集合中
}
///< 静态成员函数,断开slot 和 signal
static void do_signal_disconnect(has_slots_interface* p,
_signal_base_interface* sender) {
has_slots* const self = static_cast<has_slots*>(p);
lock_block<mt_policy> lock(self);
self->m_senders.erase(sender); ///< 将此signal从slot的signal集合中擦除
}
static void do_disconnect_all(has_slots_interface* p) {
has_slots* const self = static_cast<has_slots*>(p);
lock_block<mt_policy> lock(self);
while (!self->m_senders.empty()) {
std::set<_signal_base_interface*> senders;
senders.swap(self->m_senders); ///< 将m_senders置为空,内容交换到临时变量senders中
const_iterator it = senders.begin();
const_iterator itEnd = senders.end();
while (it != itEnd) { ///< 对每个signal调用slot_disconnect断开与该槽的连接
_signal_base_interface* s = *it;
++it;
s->slot_disconnect(p);
}
}
}
private:
sender_set m_senders; ///< 该slot对应的 信号集合
};
///< 变参类模板
template <class mt_policy, typename... Args>
class signal_with_thread_policy : public _signal_base<mt_policy> {
private:
typedef _signal_base<mt_policy> base;
protected:
typedef typename base::connections_list connections_list; ///< connections_list: std::list<_opaque_connection>
public:
signal_with_thread_policy() {} ///< ctor
///< 信号 连接
template <class desttype>
void connect(desttype* pclass, void (desttype::*pmemfun)(Args...)) {
std::cout << "111. " << "signal_with_thread_policy::connect(desttype* pclass, void (desttype::*pmemfun)(Args...))" << std::endl;
std::cout << typeid(signal_with_thread_policy).name() << std::endl;
lock_block<mt_policy> lock(this);
///< 以目标类(槽has_slots的派生类/组合类),和目标类成员函数为参数,构造一个不透明连接,然后压入该信号的 不透明连接 列表m_connected_slots 中
std::cout << "222. 以目标类(槽has_slots的派生类/组合类),和目标类成员函数为参数,构造一个不透明连接,然后压入该信号的 不透明连接 列表m_connected_slots 中" << std::endl;
std::cout << "this->m_connected_slots.push_back(_opaque_connection(pclass, pmemfun))" << std::endl;
this->m_connected_slots.push_back(_opaque_connection(pclass, pmemfun));
///< 调用目标类型(槽has_slots的派生类/组合类)的, signal_connect 方法,将该信号和槽(目标类成员函数)连接
pclass->signal_connect(static_cast<_signal_base_interface*>(this));
std::cout << "666. connect signal & slots together success." << std::endl;
}
///< 信号 发射
void emit(Args... args) {
lock_block<mt_policy> lock(this);
this->m_current_iterator = this->m_connected_slots.begin();
///< 迭代器 遍历 不透明连接 列表m_connected_slots
while (this->m_current_iterator != this->m_connected_slots.end()) {
///< get 一个 _opaque_connection 不透明连接实例 conn
_opaque_connection const& conn = *this->m_current_iterator;
++(this->m_current_iterator);
/**< 调用_opaque_connection的 emit方法 ==> _opaque_connection::emitter<DestT, Args...>
* ==> (static_cast<DestT*>(self->pdest)->*(pm))(args...);
* aka. 最终调用目标类型(槽has_slots的派生类/组合类)的成员函数
*/
std::cout << "888. signal_with_thread_policy::emit(Args... args)" << std::endl;
std::cout << " 调用_opaque_connection的 emit方法 ==> _opaque_connection::emitter<DestT, Args...> ==> (static_cast<DestT*>(self->pdest)->*(pm))(args...); aka. 最终调用目标类型(槽has_slots的派生类/组合类)的成员函数" << std::endl;
conn.emit<Args...>(args...);
}
}
void operator()(Args... args) {
std::cout << "777. signal_with_thread_policy::operator()" << std::endl;
emit(args...); } ///< 操作符重载 aka signal_with_thread_policy的对象 x()
};
// Alias with default thread policy. Needed because both default arguments
// and variadic template arguments must go at the end of the list, so we
// can't have both at once.
///< using: 定义类型别名 或者 模板别名
template <typename... Args>
using signal = signal_with_thread_policy<SIGSLOT_DEFAULT_MT_POLICY, Args...>;
// The previous verion of sigslot didn't use variadic templates, so you would
// need to write "sigslot::signal2<Arg1, Arg2>", for example.
// Now you can just write "sigslot::signal<Arg1, Arg2>", but these aliases
// exist for backwards compatibility.
template <typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal0 = signal_with_thread_policy<mt_policy>;
template <typename A1, typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal1 = signal_with_thread_policy<mt_policy, A1>;
template <typename A1,
typename A2,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal2 = signal_with_thread_policy<mt_policy, A1, A2>;
template <typename A1,
typename A2,
typename A3,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal3 = signal_with_thread_policy<mt_policy, A1, A2, A3>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal4 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal5 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename A6,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal6 = signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename A6,
typename A7,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal7 =
signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7>;
template <typename A1,
typename A2,
typename A3,
typename A4,
typename A5,
typename A6,
typename A7,
typename A8,
typename mt_policy = SIGSLOT_DEFAULT_MT_POLICY>
using signal8 =
signal_with_thread_policy<mt_policy, A1, A2, A3, A4, A5, A6, A7, A8>;
} // namespace sigslot
#endif /* RTC_BASE_THIRD_PARTY_SIGSLOT_SIGSLOT_H_ */
main.cpp
/*************************************************************************
> File Name: main.cpp
> Author: XXDK
> Email: [email protected]
> Created Time: Fri 31 Aug 2018 09:38:20 AM CST
************************************************************************/
#include<iostream>
#include"sigslot.h"
#include<unistd.h>
#include<stdio.h>
using namespace std;
using namespace sigslot;
class Sender
{
public:
sigslot::signal2<std::string, int> m_pfnsigDanger;
void Panic() {
static int nVal = 0;
char szVal[20] = {0};
snprintf(szVal, 20, "help--%d", nVal);
//m_pfnsigDanger.emit(szVal, nVal++); ///< emit signal
m_pfnsigDanger(szVal, nVal++); ///< operator "()" overload
}
};
class Receiver: public sigslot::has_slots<>
{
public:
void OnDanger(std::string strMsg, int nVal) {
std::cout << "ccc. Receiver::OnDanger(std::string, int)" << std::endl;
std::cout << strMsg.c_str() << "==> " << nVal << std::endl;
}
};
int main()
{
Sender sender;
Receiver recever;
sender.m_pfnsigDanger.connect(&recever, &Receiver::OnDanger);
while (1) {
std::cout << std::endl;
std::cout << "==================================> in while..." << std::endl;
sender.Panic();
sleep(2);
}
return 0;
}