- 1、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
全是精心选出来的精品文档,对您的生活和学习将会有所帮助!
boost源码剖析之:多重回调机制signal
刘未鹏
C++的罗浮宫(/pongba)
boost库固然是技术的宝库,却更是思想的宝库。大多数程序员都知道如何应用command,observer等模式,却不知该如何写一个支持该模式的类。正如隔靴搔痒,无法深入。DDJ上曾有一篇文章用C++实现类似C#的event机制,不过是个雏形,比之oost.signal却又差之甚远矣。上篇:架构引入
所谓“事件”机制,简而言之,就是用户将自己的一个或多个回调函数挂钩到某个“事件”上,一旦“事件”被触发,所有挂钩的函数都被调用。
毫无疑问,事件机制是个十分有用且常用的机制,不然C#也不会将它在语言层面实现了。
但是C++语言并无此种机制。
幸运的是oost库的开发者们替我们做好了这件事(事实上,他们做的还要更多些)。他们的类称作signal,即“信号”的意思,当“信号”发出的时候,所有注册过的函数都将受到调用。这与“事件”本质上完全一样。
简单情况下,你只需要这样写:
double square(double d){return pi*r*r;} //面积
double circle(double d){return 2*pi*r;} //周长
//double(double)是一个函数类型,意即:接受一个double型参数,返回double。
signaldouble(double) sig;
sig.connect(square); //向sig注册square
sig.connect(circle);//注册circle
//触发该信号,sig会自动调用square(3.14),circle(3.14),并返回最后一个函数,circle()的返回值
double c=sig(3.14); //assert(c==circle(3.14))
signal能够维护一系列的回调函数,并且,signal还允许用户指定函数的调用顺序,signal还允许用户定制其返回策略,默认情况下返回(与它挂钩的)最后一个函数的返回值,当然你可以指定你自己的“返回策略”(比如:返回其中的最大值),其中手法,甚为精巧。另外,如果注册的是函数对象(仿函数)而非普通函数,则signal还提供了跟踪能力,即该函数对象一旦析构,则连接自动断开,其实现更是精妙无比。
俗语云:“熟读唐诗三百首,不会吟诗也会吟”。写程序更是如此。如果仔细体会,会发现signal的实现里面隐藏了许许多多有价值的思想和模式。何况boost库是个集泛型技术之大成的库,其源代码本身就是一笔财富,对于深入学习C++泛型技术是极好的教材。所以不讲应用,只讲实现,可以边读边参照boost库的源代码。另外,本文尽量少罗列代码,多分析架构和思想,并且列出的代码为了简洁起见,往往稍作简化,略去了一些细节,但是都注明其源文件,自行参照。
在继续往下读之前,建议大家先看看boost库的官方文档,了解signal的各种使用情况,这样,在经历下面繁复的分析过程时心中才会始终有一个清晰的脉络。事实上,在阅读代码之前也是从各种例子入手的。架构
Signal的内部架构,如果给出它的总体轮廓,非常清晰明了。见下图:
图一
显然,signal在内部需要一个管理设施来管理用户所注册的函数(这就是图中的slot manager),从根本上来说,boost::signal中的这个slot“管理器”就是multimap(如果你不熟悉multimap,可以参考一些STL方面的书籍(如《C++ STL》《泛型编程与STL》)或干脆查询MSDN。这里我只简单的说一下——multimap将键(key)映射(map)到键值(键和键值的类型可以是任意),就像字典将字母映射到页码一样。)它负责保存所谓的slot,每一个slot其实本质上是一个boost::function函数对象,该函数对象封装了用户注册给signal回调的函数(或仿函数)。当然,slot是经过某种规则排序的。这正是signal能够控制函数调用顺序的原因。
当你触发signal时,其内部迭代遍历“管理器”——multimap,找出其中保存的所有函数或函数对象并逐一调用它们。
听起来很简单,是不是?但是我其实略去了若干细节,譬如,如何让用户控制某个特定的连接?如何控制函数的调用顺序?如何实现可定制的返回策略?等等。
看来设计一个“industry-strength”的signal并非一件易事。事实上,非常不易。然而,虽然我们做不到,却可以看看大师们的手笔。
我们从signal的最底层布局开始,signal的底层布局十分简单,由一个基类signal_base_impl来实现。下面就是该基类的代码:
摘自boost/signals/detail/sig
文档评论(0)