1、signals2库
signals2库实现了线程安全的观察者模式,在signals2中观察者模式被称为信号/插槽(signals/slots),它是一种函数回调机制。一个信号可以关联一个或多个插槽,当信号发出时,所有关联它的插槽都会被调用。
signals2位于名字空间boost::signals2,使用需要包含头文件"boost/signals2.hpp",而且在VC下编译signals2时,应该在stdafx.h中加入预声明#define _SCL_SECURE_NO_WARNINGS,或者在项目属性->C/C++->预处理器->预处理定义中添加_SCL_SECURE_NO_WARNINGS。
2、signal
在signals2中使用signal类来表示信号,一个信号可以关联一个或多个插槽,插槽可以是函数指针、函数对象、bind表达式、function对象。调用signals的成员函数connect()来将插槽连接到信号上,对signal对象调用()即为产生一个信号(signal提供了operator()),从而导致连接的所有插槽被调用。可以看到signal的功能以及使用方式跟function很像,可以把function看做是只有一个插槽的signal。
产生信号即调用signal的operator()的返回值是一个optional类型的对象,可以使用解引用操作符*来获得真正的返回值,而且默认情况下,这个返回值是最后被调用的插槽的返回值。signal会把参数传递给所有连接的插槽。
就像function一样,signal也是一个模板类,第一个模板参数是插槽函数类型签名,除了第一个模板参数外其他的模板参数都有缺省值,所以可以只传入第一个参数。
signal::connect()的第一个参数为一个插槽,第二个参数为插入的位置,插入位置决定了插槽的调用顺序,默认值为at_back往后插入,at_front为往前插入,返回值是一个connection对象,可以这个对象来管理连接,如断开连接(disconnect)、测试连接(connected)等。
其它成员函数:
num_slots()用来获得连接的插槽的个数,empty()用来判断连接的插槽数量是否为0。
combiner()用来获取合并器,set_combiner()用来设置合并器,不过一般是在signal构造函数中直接设置合并器。
disconnect()用来断开连接,disconnect_all_slots()用来断开所有连接的插槽,signal对象析构时会自动调用disconnect_all_slots()。
使用示例:
#include "boost/signals2.hpp" int slots1(int n) { int iRet = n * n; cout << "slot1 called, return value: " << iRet << endl; return iRet; } int slots2(int n, int x) { int iRet = n * n * x; cout << "slot2 called, return value: " << iRet << endl; return iRet; } int slots3(int n) { int iRet = n * n; cout << "slot3 called, return value: " << iRet << endl; return iRet; } int slots4(int n) { int iRet = n * n; cout << "slot4 called, return value: " << iRet << endl; return iRet; } int main() { boost::signals2::signal<int(int)> sig; boost::signals2::connection con1 = sig.connect(slots1); boost::signals2::connection con2 = sig.connect(bind(slots2, _1, 100)); boost::signals2::connection con3 = sig.connect(slots3, boost::signals2::at_front); boost::signals2::connection con4 = sig.connect(slots4); bool b = con4.connected(); con4.disconnect(); b = con4.connected(); int iRet = *sig(1); cout << "return value: " << iRet << endl; return 0; }