WebRTC源代码探索之旅——多线程篇(4 - 2)

来源:互联网 发布:大数据服务器 编辑:程序博客网 时间:2024/06/05 00:10

4.4 talk_base::MessageQueue

 

现在我们正式进入多线程篇最为激动人心的部分——多路信号分离器的消息队列组件。WebRTC的多路型号分离器由2部分组成:消息队列和talk_base::SocketServer(主要实现就是talk_base::PhysicalSocketServer)。消息队列负责接受消息,并使用消息处理器(talk_base::MessageHandler的子类)处理消息。在处理完所有消息后,消息队列调用talk_base::SocketServer::Wait函数阻塞等待新的IO信号。如果有新的消息进入,消息队列会调用talk_base::SocketServer::WakeUp唤醒talk_base::SocketServer阻塞等待。这就是消息队列和talk_base::SocketServer协同工作的基本流程。

 

让我们先来看一下,消息队列的实现。消息队列的主要功能是接收和处理消息,并作为talk_base::Thread的基类出现。

 

它的主要部件(成员变量)包括:

ss_:协同工作的talk_base::SocketServer

default_ss_:默认的talk_base::SocketServer。如果在构造的时候提供talb_base::SocketServer,那么消息队列就使用用户提供的;如果没有提供,消息队列就初始化一个talk_base::PhysicalSocketServer并保存在default_ss_上,然后赋值给ss_。在消息队列析构的时候,如果default_ss_保存有默认构造talk_base::PhysicalSocketServer,那就销毁它

msgq_:消息队列,队列内的消息按照先进先出的原则立即执行

dmsgq_:延迟消息队列,队列内的消息按照指定的时间延迟执行

 

接着,我们来看一下talk_base::MessageQueue的主要成员函数:

talk_base::MessageQueue::Get:等待接收消息。

参数说明:

pmsg:存放消息的指针,用于返回消息

cmsWait:等待的时间,kForever表示无限等待

process_io:是否要求talk_base::SocketServer处理IO信号

 

talk_base::MessageQueue::PostDelayed:发送一个延迟消息(从当前时间计算延迟处理时间)

参数说明:

cmsDelay:延迟毫秒数

phandler:消息处理器(talk_base::MessageHandler的子类)

id:消息ID

pdata:MessageData指针

 

talk_base::MessageQueue::PostAt:发送一个延迟消息(直接指定延迟处理时间)

参数说明:

tstamp:消息触发的时间

phandler:消息处理器(talk_base::MessageHandler的子类)

id:消息ID

pdata:MessageData指针

 

talk_base::MessageQueue::Clear:通过指定talk_base::MessageHandler和消息ID删除消息

参数说明:

phandler:指定被删除消息的talk_base::MessageHandler

id:指定被删除消息的ID;如果该id为MQID_ANY所有与phandler相关的消息都将被删除

removed:返回所有被删除消息的列表

 

talk_base::MessageQueue::GetDelay:从现在到下一条将要触发的延迟消息的触发时间的毫秒数(无参数)

 

talk_base::MessageQueue::Dispose:请求消息引擎删除一个对象(delete对象指针)

参数说明:

doomed:将要被删除的对象的指针

 

talk_base::MessageQueue::SignalQueueDestroyed(signal slot):通知接收者(observer)消息队列将要删除(参数无)

 

talk_base::MessageQueue类的核心是talk_base::MessageQueue::Get函数。Get函数的主循环首先检查dmsgq_和msgq_是否有立即需要处理的消息。如果检查到需要立即处理的消息,就马上将该消息返回。如果没有检查到需要立即处理的消息,那么线程就阻塞等待在talk_base::SocketServer::Wait函数上。如果阻塞等待期间有新的消息进入队列或者线程需要停止退出,通过talk_base::SocketServer::WakeUp函数唤醒被阻塞的talk_base::SocketServer::Wait函数。从talk_base::SocketServer::Wait函数返回后,talk_base::MessageQueue::Get函数会重新检查是否有可以返回的消息,如果没有则再次阻塞等待在talk_base::SocketServer::Wait函数上。以上流程如下图所示:

 

 

talk_base::MessageQueue的原理大致如此。如果读者结合代码依然无法理解,我会在多线程篇的最后给出几段范例代码,并完整地展开所有函数的调用序列和调用栈。相信到时候大多数读者都能够理解WebRTC的线程架构是如何工作的。
0 0
原创粉丝点击