Sigslot 是Sarah Thompson 设计实现的C++ 事件处理的框架, 这套框架非常轻量级, 全部代码只有一个sigslot.h 文件, 其设计也非常出色, 最大限度的将事件和处理机制解耦, 并且保证了线程安全.
在WebRTC中, sigslot 是其基础的事件处理框架, 在多个模块的消息通知, 响应处理中被使用. 下文, 我们简单的来剖析下sigslot 的原理及其应用.
在C++中, 普通的事件处理也容易实现, 下面是一个简单的例子, 描述电灯开关工作:
class Switch
{
public:
virtual void Clicked() = 0;
};
class Light
{
public:
void ToggleState();
};
class ToggleSwitch : public Switch
{
public:
ToggleSwitch(Light & light) {
m_light = light;
}
virtual void Clicked() {
m_light.Toggle();
}
private:
Light & m_light;
};
// how to toggle light
Light red, white;
ToggleSwitch sw1(red), sw2(white);
sw1.Clicked();
sw2.Clicked():
有一个改进的方案是利用C++的多态, 比如设计一个虚接口: SwithableItem, 让Motor 和 Light 继承自这个虚接口. 这也是不错的思路. 不过在这里sigslot 利用C++ template, 提供了一种更加优雅的方式, 还是继续来看代码:
class Switch
{
public:
sigslot::signal0<> Clicked;
};
class Light : public sigslot::has_slot<>
{
public:
void Toggle();
};
Switch sw1, sw2;
Light red, white;
sw1.Clicked.connect(&red, &Light::Toggle);
sw2.Clicked.connect(&white, &Light::Toggle);
sw1.Clicked();
sw2.Clicked();
这段代码的功能跟上面的完全一样, 但是最大的区别在于: Switch跟Light之间的绑定关系是在运行期建立的, 跟Swtich 和 Light 本身的设计无关! 这真是令人惊叹的设计!
关于sigslot的好处, 我想已经不必多言. 读者可以去sigslot的主页上下载代码, 试着在你的工程中用一下sigslot,仔细阅读理解下其源码, 你一定会有所收获!.
下面贴一下webrtc中关于sigslot使用的代码片断:
sigslot::signal2 SignalFrameCaptured;class VideoCapturer : public sigslot::has_slots<>,
public rtc::VideoSourceInterface {
......
sigslot::signal2 SignalFrameCaptured;
};
void VideoCapturer::Construct() {
enable_camera_list_ = false;
capture_state_ = CS_STOPPED;
SignalFrameCaptured.connect(this, &VideoCapturer::OnFrameCaptured);
scaled_width_ = 0;
scaled_height_ = 0;
enable_video_adapter_ = true;
// There are lots of video capturers out there that don't call
// set_frame_factory. We can either go change all of them, or we
// can set this default.
// TODO(pthatcher): Remove this hack and require the frame factory
// to be passed in the constructor.
set_frame_factory(new WebRtcVideoFrameFactory());
}
void SignalCapturedFrame(cricket::CapturedFrame* frame) {
SignalFrameCaptured(this, frame);
}
Reference:
1 Sigslot 项目主页: http://sigslot.sourceforge.net/