Sigslot-WebRTCにおけるイベント処理メカニズム
2882 ワード
SigslotはSarah Thompsonが設計し実現したC++イベント処理のフレームワークであり、このフレームワークは非常に軽量で、すべてのコードは1つのsigslotしかない.hファイルは、その設計も非常に優れており、イベントと処理メカニズムを最大限にデカップリングし、スレッドの安全を保証している.
WebRTCではsigslotがそのベースとなるイベント処理フレームワークである、複数のモジュールのメッセージ通知、応答処理に用いられる.以下、sigslotの原理とその応用を簡単に分析する.
C++では、通常のイベント処理も容易に実現でき、以下は簡単な例であり、電灯スイッチの動作を説明する.
上のコードはよく機能するが、ToggleSwitchはLightの参照を得る必要があり、その後、LightのToggle関数を明示的に呼び出す必要があるという弊害がある.将来Switchでモーターを制御したい場合は、コードを変更しなければなりません.
1つの改良案はC++の多態を利用して、例えば1つの虚のインタフェースを設計する:SwithableItem、MotorとLightにこの虚のインタフェースから継承させる.これもいい考えだ.しかし、ここでsigslotはC++templateを利用して、より優雅な方法を提供しています.やはりコードを見続けます.
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():
上のコードはよく機能するが、ToggleSwitchはLightの参照を得る必要があり、その後、LightのToggle関数を明示的に呼び出す必要があるという弊害がある.将来Switchでモーターを制御したい場合は、コードを変更しなければなりません.
1つの改良案はC++の多態を利用して、例えば1つの虚のインタフェースを設計する: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<:videoframe> { ...... 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/