Sigslot-WebRTCにおけるイベント処理メカニズム


SigslotはSarah Thompsonが設計し実現したC++イベント処理のフレームワークであり、このフレームワークは非常に軽量で、すべてのコードは1つの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():


上のコードはよく機能するが、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/