Sigslot介绍

最近在看webrtc开源代码,最底层封装的消息机制,是基于其has_slots,搜索了一下其资料发现是一个很好用的C++库,先对其简单介绍一下。

插槽机制

插槽系统常用的有三种:boost的signals,sigslot,sigc++
基本功能有:
1.connect
2.disconnect
3.emit

sigslot

sigslot是一个线程安全、类型安全,用C++实现的sig/slot机制(sig/slot机制就是对象之间发送和接收消息的机制)的开源代码库。是一个非常好用的库,只有一个头文件sigslot.h

优点
- 不用担心空回调,当回调对象析构时会自动disconnect
- 支持多线程,线程安全,有锁

缺点
- 只能回调void类型函数,不支持返回值。boost中的signals库架构类似,支持返回值,但引入了boost中的其他库
- slot没有优先级,不能动态调整回调队列中的先后顺序

用法

发送信号
比如ReportError信号,当调用ReportError(“Something went wrong”, ERR_SOMETHING_WRONG);时候,将自动调用ReportError的emit成员函数发出一个信号。发给谁呢?

连接信号
通过调用sig的connect函数建立sig和slot间的对应关系。Connect函数接收两个参数,一个是消息目的对象的地址(指针), 另一个是目的对象的成员函数指针(slot)。为了让整个机制有效运行,目的类必须从has_slots<>继承,并且sig/slot参数 类型必须一致。也可以将一个sig连接到多个slot上,这样每次sig发出信号的时候,每个连接的slot都能收到该信号。

断开信号
通过调用sig的disconnect函数断开sig和slot之间的连接,只有一个参数:目的对象的地址。一般不需要显式调用 disconnect函数,在sig类和目的类(包含slot函数的类)析构函数中将自动调用disconnect断开sig和slot的连接。也可使用 disconnect_all断开该sig的所有slot。

实例

#include "sigslot.h"

using namespace sigslot;
using namespace std;

class Switch
{
public:
    signal0<> Clicked;
};

class Light :public has_slots <>
{
public:
    Light(bool state)
    {
        b_state = state;
        DisplayState();
    }

    void ToggleState()
    {
        b_state = !b_state;
        DisplayState();
    }

    void TurnOn()
    {
        b_state = TRUE;
        DisplayState();
    }

    void TurnOff()
    {
        b_state = FALSE;
        DisplayState();
    }

    void DisplayState()
    {
        printf("The State is %d\n", b_state);
    }

private:
    bool b_state;
};

int main(int argc, const char* argv[])
{
    Switch sw1, sw2, all_on, all_off;
    Light lp1(TRUE);
    Light lp2(FALSE);

    sw1.Clicked.connect(&lp1, &Light::ToggleState);
    sw2.Clicked.connect(&lp2, &Light::ToggleState);
    all_on.Clicked.connect(&lp1, &Light::TurnOn);
    all_on.Clicked.connect(&lp2, &Light::TurnOn);
    all_off.Clicked.connect(&lp1, &Light::TurnOff);
    all_off.Clicked.connect(&lp2, &Light::TurnOff);

    sw1.Clicked();
    sw2.Clicked();
    all_on.Clicked();
    all_off.Clicked();

    sw1.Clicked.disconnect(&lp1);
    sw2.Clicked.disconnect(&lp2);
    all_on.Clicked.disconnect(&lp1);
    all_on.Clicked.disconnect(&lp2);
    all_off.Clicked.disconnect(&lp1);
    all_off.Clicked.disconnect(&lp2);

    return 0;
}

备注
从官网上下载下sigslot.h文件之后,引入工程之后会报错误:

Error 2 error C2146: syntax error : missing ‘;’ before identifier ‘const_iterator’ e:\visual studio 2013\test\test\sigslot.h 419 1 Test

修改:

typedef std::set<_signal_base *> sender_set;
typedef typename sender_set::const_iterator const_iterator;

原因:
因为set本身就是模板,在其模板参数未确定之前,也就是_signal_base 的具体类型没有确定之前,引用其class内部定义的type,这个type也是未知的,加上typename就是告诉编译器先不管具体类型,等模板实例化的时候再确定吧

你可能感兴趣的:(webrtc)