OpenRTMFP/Cumulus Primer(22)线程逻辑分析之一:RTMFPServer线程的启动和等待
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;}Cumulus 中实现了一个 StartableProcess 类,该类继承了 Runnable,就是上面那个 gift 喽。
class StartableProcess : public Poco::Runnable{public: StartableProcess(Startable& startable);private: void run(); Startable& _startable;};可以看到其中有Startable& _startable引用成员,它并没有继承 Runnable,而是封装了StartableProcess和Poco::Thread:
Poco::Thread _thread;StartableProcess _process;这里Startable封装了一个StartableProcess成员,与StartableProcess是有所区别的。接下俩我们看他们是怎么用的。
我们可以看到在 Startable 类的构造函数中初始化了_process成员,初始化线程成员并传入线程名,设定标志域(Flag Field)_stop为true,因为它还没有调用启动函数。
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 SocketHandlerRTMFPServer 的构造函数:
RTMFPServer::RTMFPServer(UInt32 cores) : Startable("RTMFPServer"), _sendingEngine(cores), _receivingEngine(cores), _pCirrus(NULL), _handshake(_receivingEngine, _sendingEngine, *this, _edgesSocket,*this,*this), _sessions(*this) {}其中在初始化时调用了其父类的构造函数。接下来就要启动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;}在运行状态下,_stop为false,而默认参数timeout为0,所以会调用:
_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
-