OpenRTMFP/Cumulus Primer(22)執行緒邏輯分析之一:RTMFPServer執行緒的啟動和等待

鍾超發表於2012-08-05

OpenRTMFP/Cumulus Primer(22)RTMFPServer執行緒的啟動和等待

  • 作者:柳大·Poechant(鍾超 Michael)
  • 部落格:Blog.csdn.net/poechant
  • 郵箱:zhongchao.ustc@gmail.com
  • 日期:August 5th, 2012

1 Poco::Thread

Cumulus 大量使用了 Poco 的執行緒庫。一個簡單的 Poco 執行緒的使用例項如下:

class PoechantRunnable: public Poco::Runnable {
    virtual void run() {
        // your codes
    }
};

int main() {
    PoechantRunnable runnable;  // Image that it's a gift
    Poco::Thread thread;        // And… thread is just like your girl
    thread.start(runnable);     // Okay, give your sweet babe the gift :)
    thread.join();
    return 0;
}

2 封裝一個可執行執行緒的類

Cumulus 中實現了一個 StartableProcess 類,該類繼承了 Runnable,就是上面那個 gift 嘍。

class StartableProcess : public Poco::Runnable{
public:
    StartableProcess(Startable& startable);
private:
    void run();
    Startable& _startable;
};

可以看到其中有Startable& _startable引用成員,它並沒有繼承 Runnable,而是封裝了StartableProcessPoco::Thread

Poco::Thread            _thread;
StartableProcess        _process;

這裡Startable封裝了一個StartableProcess成員,與StartableProcess是有所區別的。接下倆我們看他們是怎麼用的。

3 啟動RTMFPServer執行緒

我們可以看到在 Startable 類的建構函式中初始化了_process成員,初始化執行緒成員並傳入執行緒名,設定標誌域(Flag Field)_stoptrue,因為它還沒有呼叫啟動函式。

Startable::Startable(const string& name)
    : _name(name),
      _thread(name),
      _stop(true),
      _haveToJoin(false),
      _process(*this) {
}

初始化_process時,呼叫StartableProcess建構函式:

StartableProcess::StartableProcess(Startable& startable)
    : _startable(startable){
}

傳入_startable的引用。在 Cumulus 中所有的執行緒的可執行類都是繼承自 Startable 類的,然後通過呼叫 start() 來啟動,啟動後會響應到 run()。下面我們以 RTMFPServer 執行緒為例。

RTMFPServer 類是繼承自 Startable 類的:

class RTMFPServer
    : private Gateway,
      protected Handler,
      private Startable,
      private SocketHandler

RTMFPServer 的建構函式:

RTMFPServer::RTMFPServer(UInt32 cores)
    : Startable("RTMFPServer"),
      _sendingEngine(cores),
      _receivingEngine(cores),
      _pCirrus(NULL),
      _handshake(_receivingEngine,
      _sendingEngine,
      *this,
      _edgesSocket,*this,*this),
      _sessions(*this) {
}

其中在初始化時呼叫了其父類的建構函式。接下來就要啟動RTMFPServer執行緒了。

所線上程 呼叫者 函式
主執行緒 main(…)
主執行緒 RTMFPServer物件 RTMFPServer::start()
主執行緒 RTMFPServer物件 Startable::start()
主執行緒 RTMFPServer從Startable繼承來的Thread成員 Thread::start(…)
RTMFPServer RTMFPServer物件從Startable繼承來的StartableProcess成員 StartableProcess::run()
RTMFPServer RTMFPServer物件 RTMFPServer::prerun()
RTMFPServer RTMFPServer物件 Startable::prerun()
RTMFPServer RTMFPServer物件 RTMFPServer::run()

4 RTMFPServer執行緒等待

RTMFPServer::run()實現執行緒的持續執行,主要是依靠這兩行程式碼:

while (!terminate)
    handle(terminate);

handle(…)函式很簡單,如下只進行了sleep(...)giveHandle()兩個操作。

void RTMFPServer::handle(bool& terminate){
    if (sleep() != STOP) {
        giveHandle();
    } else
        terminate = true;
}

sleep(…)是 RTMFPServer 是從 Startable 繼承而來的,宣告如下:

WakeUpType sleep(Poco::UInt32 timeout=0);

定義如下:

Startable::WakeUpType Startable::sleep(UInt32 timeout) {
    if (_stop)
        return STOP;
     WakeUpType result = WAKEUP;
     if (timeout>0) {
         if (!_wakeUpEvent.tryWait(timeout))
             result = TIMEOUT;
     } else {
         _wakeUpEvent.wait();
     }
    if (_stop)
        return STOP;
    return result;
}

在執行狀態下,_stopfalse,而預設引數timeout0,所以會呼叫:

_wakeUpEvent.wait();

這個_wakeUpEvent成員是一個Poco::Event物件,Poco::Event有一個使用方式就是在呼叫Poco::Event::wait()後,會一直等待Poco::Event::set()被呼叫後,才會跳出 wait 的狀態。在 Cumulus 中 set 的動作是由:

  • RTMFPServer::requestHandle()
  • PoolThread::push(Poco::AutoPtr<RunnableType>& pRunnable)

執行的。

-

轉載請註明柳大·Poechant(鍾超)的CSDN部落格:Blog.CSDN.net/Poechant

-

相關文章