sigslot库源码分析

言归正传,sigslot是一个用标准C++语法实现的信号与槽机制的函数库,类型和线程安全。提到信号与槽机制,恐怕最容易想到的就是大名鼎鼎的Qt所支持的对象之间通信的模式吧。不过这里的信号与槽虽然在概念上等价与Qt所实现的信号与槽,但是采用的仅仅是标准C++语法,不像Qt采用了扩展C++语言的方式(Qt需要使用moc工具对代码预处理之后,才能由标准的C++编译器进行编译)。

众所周知,C++是一门特性众多的语言,其支持多种编程范式。虽然C++在一定程度上支持OOP编程,但是C++这种“静态消息机制”的语言一直没有实现对象级别的delegate机制,而C++之父Bjarne主张的“库扩展胜于语言扩展”的做法使得各种解决方案层出不穷。除了信号与槽机制,C++11正式加入的std:bind/std::function组合也提供了优秀的解决方案。这里所说的信号与槽机制也是一种对象间通信的机制,具体的讨论也可以看看sigslot相关介绍中的内容。

sigslot主页: http://sigslot.sourceforge.net

sigslot文档: http://sigslot.sourceforge.net/sigslot.pdf

sigslot 库的用法文档中已然很明了了,所以在这里就不赘述了。接下来我们看看这个库的实现。源码分析的方法有很多种,具体到库代码的分析的方法,我喜欢的是先研究库的功能,直到能写出一个demo程序为止。研究一个库的前提是你得会用它,熟悉它的接口。读完文档,很容易就写出了下面的测试代码:

#include #include "sigslot.h"using namespace sigslot;class Switch
{
public:signal0<> clicked;
};class Light : public has_slots<>
{
public:void turn_on(){std::cout << "Turn on ~" << std::endl;}};int main(int argc, char *argv[])
{Light lit1;Switch swh;swh.clicked.connect(&lit1, &Light::turn_on);swh.clicked.emit();return 0;
}

使用方法很简单。从这里我们就能看出来,这个库无非就是在信号那一端保存了这个信号所绑定的函数指针,在槽函数这一端保存了其绑定的信号而已。接下来的问题实际上就是采用合理的数据结构来处理问题了。

sigslot库简单到只有一个头文件 sigslot.h ,打开后洋洋洒洒几千行代码,其实仔细看看绝大多数代码都是为了适应参数数量不同的成员函数指针的定义,为其扩展的模版代码。从定义上看,这个库支持 0~8 个参数的成员函数绑定。在纸上画一下类的继承关系,很容易就得到了如下的函数继承图( IDE 有相关的工具也可以拿来用 ~ ) :

从这个图上看,其实代码关系已经很清晰了。 实现了槽函数的类需要继承 has_slots 类。而 has_slots类 拥有一个 std::set<_signal_base<mt_policy>*> 类型的容器(所有的 mt_policy 其实是库定义的三种锁策略而已[单线程无锁、多线程共享全局锁、多线程局部锁])。所有的 _signal_base[0-8] 的类持有各自的 std::list<_connection_base[0-8]<mt_policy > > 的list容器,而 _connection_base[0-8] 则分别封装了0~8个参数的成员函数的指针。

这里的重复代码是很多的,作为分析的话完全可以每中类代码只留下一个,这样所有的代码就精简到只有6个类了(反正别的也只是为了适应参数个数写的模版罢了,代码除了参数个数外都是一样的)。

至于前面说到的锁,其实也只是因为C++ STL库中的容器本身不是线程安全的,需要在外部加锁。锁的实现很平常,另外用C++ RAII手法封装的lock_block类也是常见的用法。唯一需要注意的是,这个库在使用了信号与槽的用户类发生了拷贝构造时,其信号与槽的绑定关系也会被拷贝,所以代码中的类都自行编写了相关的拷贝构造函数。这里稍微解释下,如果A类的a对象的x信号和B类的b1对象的y函数绑定,然后用b1初始化构造b2(即 B b2(b1))。这时候,A类的a对象的x信号也会绑定到b2对象的y函数。这个特性我感觉有点莫名其妙,而且使得代码复杂了不少(我觉得没必要这么设计,用户需要这个特性的话,自己再调用一次绑定函数就是了)。

知晓了基本的原理之后,看代码就很容易了。比如在拥有信号和拥有槽函数的对象析构时,会自动的取消掉之前的绑定,代码很清晰易读的。下面是我自己根据sigslot的原理,简化出来的代码,大家可以先看看然后去读sigslot的源码会简单很多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509770.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mysql for linux 安装

Mysql for linux 安装&#xff1a; 第一步&#xff0c;参考这个链接至第四步为止 https://jingyan.baidu.com/article/cd4c2979209c32756e6e60e1.html 第二步&#xff1a;使用rpm -qa | grep mysql 查询安装状态 第三步&#xff1a;使用/etc/rc.d/init.d/mysqld status 检…

Hue开发指南 - 提交 Spark 程序

目录 Hue开发指南 1.Spark文件打包成一个Jar包提交Hue运行 1.1 上传Spark Jar包至HDFS文件系统 1.2.Hue中创建Spark任务 2.多jar包导入执行&#xff08;依赖jar包与主程序jar包分开打包&#xff09; 2.1 修改worksapce 2.2 添加程序依赖jar包 Hue开发指南 Hue是面向 Had…

如何缩小码农和高手的差距

为什么同样的时间有的人可以漂亮的完成工作&#xff0c;而有些人废了很大的力气也没有完成&#xff1f;前者我们常常称之为“大牛”&#xff0c;后者我们常常叫他们“菜鸟”。当然“大牛”都是相对而言的&#xff0c;“大牛”也不可能方方面面都非常厉害&#xff0c;换句话说大…

OpenResty 安装,收集日志保存到文本文件

目录 安装 1.安装相关类库 2.安装编译openresty 3.编写配置启动openresty服务 4.通过 openresty 保存日志数据到系统 安装 1.安装相关类库 yum install -y readline-devel pcre-devel openssl-devel gcc 2.安装编译openresty wget https://openresty.org/download/open…

暗时间-领悟

作者&#xff1a;排长链接&#xff1a;https://www.zhihu.com/question/20689852/answer/23227406来源&#xff1a;知乎著作权归作者所有&#xff0c;转载请联系作者获得授权。第一次看到“暗时间”这个词&#xff0c;我的第一反应是有点不屑&#xff0c;又是一个概念噱头吧。直…

Openresty Nginx 负载均衡

目录 OpenResty Openresty 服务配置文件 启动Openresty服务 测试调用接口 Nginx 负载均衡服务 nginx 配置文件 启动服务 实现功能 测试结果 这里实现个简单的负载均衡&#xff0c;只做功能展示&#xff08;实际业务比这复杂高&#xff0c;单台服务器无法满足需求的情况…

总结--美丽的敷衍

我看新年 转眼间&#xff0c;2015已经悄然离去&#xff0c;正像2015年刚来时候感叹2014的白驹过隙。年年岁岁花相似&#xff0c;岁岁年年人不同。时间过去了&#xff0c;自己又有如何的不同呢&#xff1f;客观的说&#xff0c;这一年有了一定的长进&#xff0c;但总感觉失去/错…

Hadoop Yarn REST API未授权漏洞利用挖矿分析

目录 一、背景情况 二、 漏洞说明 攻击步骤&#xff1a; 三、入侵分析 四、安全建议 清理病毒 安全加固 五、IOCs 一、背景情况 5月5日腾讯云安全曾针对攻击者利用Hadoop Yarn资源管理系统REST API未授权漏洞对服务器进行攻击&#xff0c;攻击者可以在未授权的情况…

读书-悟

作者&#xff1a;梅芳growing链接&#xff1a;https://www.zhihu.com/question/20689852/answer/95018631来源&#xff1a;知乎著作权归作者所有&#xff0c;转载请联系作者获得授权。《暗时间》这本书&#xff0c;我读过3遍&#xff0c;第一便是在大三时&#xff0c;第二遍是用…

Linux shell编程学习总结

主要内容&#xff1a; shell编程sed命令awk命令crontab定时器 什么是Shell&#xff1f; Shell是用户与内核进行交互操作的一种接口&#xff0c;目前最流行的Shell称为bash Shell Shell也是一门编程语言<解释型的编程语言>&#xff0c;即shell脚本 一个系统可以存在多…

Flink ProcessFunction 介绍使用

目录 实现功能 代码 测试 问题 官网描述&#xff1a;https://ci.apache.org/projects/flink/flink-docs-release-1.10/zh/dev/stream/operators/process_function.html The ProcessFunction is a low-level stream processing operation, giving access to the basic build…

Flink keyby 数据倾斜问题处理

上一篇我们使用keyby后发现数据严重倾斜 https://datamining.blog.csdn.net/article/details/105316728 大概看下问题所在&#xff0c;大量数据在一个subtask中运行 这里我们使用两阶段keyby 解决该问题 之前的问题如下图所示 我们期望的是 但我们的需要根据key进行聚合统计&a…

java中正则表达式

package com.test;import java.util.Scanner;public class M1001{public static void main(String[] args) {String input null;Scanner sc new Scanner(System.in);while(sc.hasNext()){inputsc.nextLine();String regex "^1[3|4|5|7|8][0-9]{9}$";//为表达式模板…

读书-时间(反思)

每一天的时间都非常多&#xff0c;下班以后的时间&#xff0c;周末闲暇的时间&#xff0c;但是时间这么多&#xff0c;自己往往不知道该拿它来干什么&#xff0c;每天下完班以后&#xff0c;回到家&#xff0c;打开电脑&#xff0c;打开手机&#xff0c;首先看一看QQ&#xff0…

Kafka 优化参数 unclean.leader.election.enable

Kafka 某个节点挂掉&#xff0c;导致整个服务异常&#xff0c;为了保证服务容灾&#xff0c;可对下面几个参数进行调整 unclean.leader.election.enabletrue min.insync.replicas1 offsets.topic.replication.factor3 这三个配置什么意思呢? 依次来看一下&#xff1a; unclean…

linux中iptables对防火墙的操作

Iptables教程 1. iptables防火墙简介 Iptables也叫netfilter是Linux下自带的一款免费且优秀的基于包过滤的防火墙工具&#xff0c;它的功能十分强大&#xff0c;使用非常灵活&#xff0c;可以对流入、流出、流经服务器的数据包进行精细的控制。iptables是Linux2.4及2.6内核中…

读书--好书

说到好书&#xff0c;我觉得对于每一个人来说&#xff0c;都有自己人生中的一本好书&#xff0c;她的内容能够引起我们的共鸣&#xff0c;认识到自己的不足之处&#xff0c;并且能够指引我们如何去改变它&#xff0c;去战胜它&#xff0c;从而使自己获取进步&#xff0c;得到升…

Web Components入门不完全指北

目前流行的各类前端框架&#xff0c;不管是react, angular还是vue&#xff0c;都有一个共同点&#xff0c;那就是支持组件化开发&#xff0c;但事实上随着浏览器的发展&#xff0c;现在浏览器也原生支持组件式开发&#xff0c;本文将通过介绍Web Components 的三个主要概念&…

Flink 1.9 CDH 6.3 集成

目录 1.下载准备文件 2.felink csa jar包准备 3.将 Flink Parcel放入httpd目录下 4.配置CDH Flink Parcel 5.安装Flink 1.下载准备文件 https://archive.cloudera.com/csa/1.0.0.0/csd/FLINK-1.9.0-csa1.0.0.0-cdh6.3.0.jarhttps://archive.cloudera.com/csa/1.0.0.0/parc…