Skip to content

sigslots

本文分析 sigslots 是什么

QT中实现的有sigslot组件,但是不能在外部独立使用
webrtc中使用了这个独立的sigslots库
http://sigslot.sourceforge.net/.
本文试图描述一下这个sigslot组件的用法

sigslots解决什么问题

看一下官方文档中的例子
 1class Switch
 2{
 3public:
 4    virtual void Clicked() = 0;
 5};
 6
 7class Light
 8{
 9public:
10    void ToggleState();
11    void TurnOn();
12    void TurnOff();
13};
在不修改Switch和Light的代码的情况下,要想让Switch对象控制Light对象
需要写一个ToggleSwitch类,实现Switch接口,把Light作为成员变量,如下
 1class ToggleSwitch : public Switch
 2{
 3public:
 4    ToggleSwitch(Light &lp)
 5    {
 6        m_lp = lp;
 7    }
 8    virtual void Clicked()
 9    {
10        m_lp.ToggleState();
11    }
12
13private:
14    Light &m_lp;
15};
16
17Light lp1, lp2;
18ToggleSwitch tsw1(lp1), tsw2(lp2);
使用sigslots后的代码如下
 1class Switch
 2{
 3public:
 4    signal0<> Clicked;
 5};
 6class Light : public has_slots<>
 7{
 8public:
 9    void ToggleState();
10    void TurnOn();
11    void TurnOff();
12};
13Switch sw1, sw2;
14Light lp1, lp2;
15
16sw1.Clicked.connect(&lp1, &Light::ToggleState);
17sw2.Clicked.connect(&lp2, &Light::ToggleState);
我们把signal比作插头
slot比作插座
每一个插头都可以插入一个插座的某个位置上

image

后续如果想添加功能也更方便,如下
 1Switch sw3, sw4, all_on, all_off;
 2Light lp3, lp4;
 3sw3.Clicked.connect(&lp3, &Light::ToggleState);
 4sw4.Clicked.connect(&lp4, &Light::ToggleState);
 5
 6all_on.Clicked.connect(&lp1, &Light::TurnOn());
 7all_on.Clicked.connect(&lp2, &Light::TurnOn());
 8all_on.Clicked.connect(&lp3, &Light::TurnOn());
 9all_on.Clicked.connect(&lp4, &Light::TurnOn());
10
11all_off.Clicked.connect(&lp1, &Light::TurnOff());
12all_off.Clicked.connect(&lp2, &Light::TurnOff());
13all_off.Clicked.connect(&lp3, &Light::TurnOff());
14all_off.Clicked.connect(&lp4, &Light::TurnOff());

sigslots 信号参数

signal和slot支持多个参数
每个参数都支持自定义类型

比如
signal0<>定义了零个参数的signal
signal1<type1>定义了一个参数的signal
signal2<type1, type2>定义了二个参数的signal

比如以下例子
 1class Window
 2{
 3public:
 4    enum WindowState
 5    {
 6        Minimised,
 7        Normal,
 8        Maximised
 9    };
10    signal1<WindowState> StateChanged;
11    signal2<int, int> MovedTo;
12    signal2<int, int> Resized;
13};
14
15class MyControl : public Control, public has_slots<>
16{
17public:
18    void OnStateChanged(WindowState ws);
19    void OnMovedTo(int x, int y);
20    void OnResize(int x, int y);
21};
22
23Window w;
24MyControl c;
25
26w.StateChanged.connect(&c, &MyControl::OnStateChanged);
27w.MovedTo.connect(&c, &MyControl::OnMovedTo);
28w.Resized.connect(&c, &MyControl::OnResize);

sigslots 发出信号

连接完signal和slot后
可以使用signal向slot发出信号
 1// 定义信号
 2signal2<char *, int> ReportError;
 3
 4// 发出信号,有两种方法
 5
 6// 方法一
 7ReportError("Something went wrong", ERR_SOMETHING_WRONG);
 8
 9// 方法二
10ReportError.emit("Something went wrong", ERR_SOMETHING_WRONG);
sigslots强大的一点是一个信号可以同时connect多个slots
每次用上面的方法发出信号后,所有connect的slots都会收到信号
但是sigslots库目目前的实现不保证slots收到信号的顺序,也不支持优先级

sigslots实现

待补充