Unix/C++--信号与槽机制的理解

1 简介

  • 信号槽是观察者模式的一种实现,或者说是一种升华。
  • 一个信号就是一个能够被观察的事件,或者至少是事件已经发生的一种通知;一个槽就是一个观察者,通常就是在被观察的对象发生改变的时候——也可以说是信号发出的时候——被调用的函数;信号和槽是多对多的关系。一个信号可以连接多个槽,而一个槽也可以监听多个信号。信号可以有附加信息。
  • 信号槽这一术语最初来自 Trolltech 公司的 Qt 库(现在已经被 Nokia 收购)。1994年,Qt 的第一个版本发布,为我们带来了信号槽的概念。这一概念立刻引起计算机科学界的注意,提出了多种不同的实现。如今,信号槽依然是 Qt 库的核心之一,其他许多库也提供了类似的实现,甚至出现了一些专门提供这一机制的工具库。

2 机制

3 与回调对比

回调紧耦合,非类型安全,
信号与槽松耦合,类型安全。

4 Qt 信号与槽

4.1 优点

  • 松耦合
  • 类型安全
  • 灵活
  • 使用简单方便

4.2 缺点

  • 速度不及回调函数 (根据网上测试数据来看在5-10倍,us级别)
    博主朝闻道:Qt 的信号与槽机制介绍(10个要注意的问题)
    速度上低于回调函数,在一台 i586-133 的机器上测试是 10 微秒(运行 Linux),[linux内核调用在低精度下在ms级别。] 如果我们要追求高效率的话,比如在实时系统中就要尽可能的少用这种机制。
    博主甲:QT 信号与槽效率测试
    在release模式下,信号槽打印平均0.5微秒,函数直接调用0.1微秒,
    两者结合应该可以肯定信号槽会比函数直接调用方式慢,大概会慢5倍

4.3 注意

  • 调用不当出现死循环
    在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发射所接收到的同样信号。
  • 槽函数执行顺序随机
    如果一个信号与多个槽相联系的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序将是随机的。
  • 宏定义不能用在 signal 和 slot 的参数中
  • 构造函数不能用在 signals 或者 slots 声明区域内。
  • 函数指针不能作为信号或槽的参数。
  • 信号与槽不能有默认参数
  • 信号与槽也不能携带模板类参数,可以使用 typedef 语句来绕过这个限制
  • 嵌套的类不能位于信号或槽区域内,也不能有信号或者槽。
  • 友元声明不能位于信号或者槽声明区内。

5 库对比

  • 信号槽系统常用的有三种:boost的signals,sigslot,sigc++
    基本功能有:connect、disconnect、emit
  • sigslot优缺点
    优点
    1.不用担心空回调,当回调对象析构时会自动disconnect
    2.支持多线程,线程安全,有锁
    缺点
    1.只能回调void类型函数,不支持返回值。boost中的signals库架构类似,支持返回值,但引入了boost中的其他库
    2.slot没有优先级,不能动态调整回调队列中的先后顺序
    注:
    slot函数(被回调的函数)就是普通的成员函数,但有以下限制:
    1.返回值必须为void
    2.Slot参数个数范围为0-8个
    3.实现slot的类必须继承自has_slots<> 1,2是sigslot库作者的限制,作者权衡各方面因素后做出的决定,如果你觉得有必要你可以修改sigslot代码取消该限制,而3是sigslot的机制基础,必须遵守,除非你自己重新写个sigslot
  • from 朝闻道
    C++的其它signal-slot实现(10来个) good
    在这里插入图片描述
  • pbhogan/Signals介绍中,强调比libsigc ++,sigslot和boost.signals更简单,更高效。但是14年后没有维护过,暂且不去研究。
  • libsigc ++: gtkmm使用libsigc ++来包装GTK +信号系统。 它不依赖于GTK +或gtkmm。(GTK能用,说明linux使用完全没问题)

6 libsigc ++使用

  • libsigc++是一个callback的完整包装,Bjarne Stroustrup都对libsigc++大为推荐。
  • 从github连接 下载
  • 选择分支,博主选17v3
  • ubuntu中解压
cd libsigcpp
mkdir release
cd release
cmake -D CMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=/home/myname/Desktop/local ..
make
make install
then success

貌似头文件太多了,库也多。先用着,后面封装自己的,尽量轻量化。
链接libsigc++AddRelease
使用:
信号槽库:sigslot.h和sigc++使用
libsigc++库的使用
介绍一个类型安全的回调库:libsigc++
libsigc+±1.2.5库的使用

7 使用注意事项

信号和槽的绑定connect在构造函数中执行,如果放在别的地方可能一次emit sig,slot函数多次执行

8 示例

8.1 类内slot connect 别的类sig

sigc::connection ccSg1 = sg1.connect(sigc::ptr_fun(&func1));
class mySlot: public : sigc::trackable
{
public:
    int func2(char*, double)(){}
} obj;
sigc::connection ccSg2 = sg2.connect(sigc::mem_fun2(obj,&mySlot::func));
class mySg: public : sigc::trackable
{
    mySg(){auto ccIter_Sg3 = sg3.connect(sigc::mem_fun(*this,&mySg::on_func));}
    sigc::signal2<int, char*, double>   sg3;
    int on_func(char*, double)(){}
}

参考

1、signal-slot 信号/槽(也译信号/插槽)机制
2、QT 信号与槽
3、C++的其它signal-slot实现(10来个) good
4、sigslot(c++信号槽库)源码分析
5、sigslot - C++ Signal/Slot Library
6、libsigcplusplus–github
7、pbhogan/Signals
8、c++超级好用的回调signal slot
9、Qt 之 信号槽机制及优缺点
10、Qt 信号和槽机制 优点 效率的详解
11、Qt 的信号与槽机制介绍(10个要注意的问题)
12、QT 信号与槽效率测试
13、编译方式参照–ubuntu14.04+cuda8.0(TX2宿主机)安装opencv3.0
14、libsigc++官网
15、深入理解信号槽机制(一)(大局观,讲的不错)
16、good–libsigc++库的使用
17、Sigslot介绍
18、解决如果出现了信号就触发一次,但是却调用多次的情况
19、Boost.Signals vs libsigc++
20、信号槽库:sigslot.h和sigc++使用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

worthsen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值