libjingle主线程的消息响应
Posted wongdu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了libjingle主线程的消息响应相关的知识,希望对你有一定的参考价值。
trunk\\talk\\app\\webrtc\\peerconnectionproxy.h文件中定义了PeerConnection的代理类,class PeerConnection : public PeerConnectionInterface,而#define BEGIN_PROXY_MAP(c) \\
class c##Proxy : public c##Interface所以BEGIN_PROXY_MAP(PeerConnection)展开即为: class PeerConnectionProxy : public PeerConnectionInterface。
所以在peerconnection例子的talk\\examples\\peerconnection\\client\\conductor.cc文件Conductor::InitializePeerConnection()函数调用PeerConnectionFactory::CreatePeerConnection函数,该函数通过signaling_thread_对象调用PeerConnectionFactory::CreatePeerConnection_s,在该函数中调用PeerConnectionProxy::Create函数,trunk\\talk\\app\\webrtc\\proxy.h文件中对代理类的Create函数进行定义,形式如TestProxy::Create(Thread*, TestInterface*)。所以上面PeerConnectionFactory::CreatePeerConnection_s函数中调用PeerConnectionProxy::Create创建的就是PeerConnectionProxy指针对象,而且这个指针对象最终会返回给trunk\\talk\\examples\\peerconnection\\client\\conductor.h文件中的成员变量talk_base::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;以后通过peer_connection_调用的函数其实都是PeerConnectionProxy::XXX。
基于以上两段的分析,所以在主线程中调用signaling_thread_->Send时,Win32SocketServer::Wait和Win32SocketServer::WakeUp函数中消息的打印次序是,第一次调用先打印Wait,然后是打印两次WakeUp,当以后调用signaling_thread_->Send时,则是先打印两次Wait,然后再打印两次WakeUp。其中后面响应signaling_thread_->Send时,先打印的Wait事实上是相当于消耗掉在前一次执行signaling_thread_->Send发送消息时,Thread::Send函数中最后一条语句current_thread->socketserver()->WakeUp();。而第二个Wait才是阻塞当前的线程即主线程。当执行signaling_thread_->Send发送消息会打印两次WakeUp,其中第二次即Thread::Send函数中最后一条语句current_thread->socketserver()->WakeUp();而第一次则是signaling_thread_线程的消息响应循环种执行的Thread::ReceiveSends函数中的smsg.thread->socketserver()->WakeUp();。
在响应第四个消息MSG_CREATE_VIDEOSOURCE时,PeerConnectionFactory::CreateVideoSource_s会调用VideoSource::Create函数进而调用VideoSource::Initialize,该函数又调用ChannelManager::StartVideoCapture,在这个函数中通过worker_thread_->Invoke来执行CaptureManager::StartVideoCapture,当worker_thread_线程消息响应循环中执行CaptureManager::StartVideoCapture中最终会调用VideoCapturer::SetCaptureState,而这个函数中通过主线程即main函数中的talk_base::Win32Thread w32_thread;来调用thread_->Post发送MSG_STATE_CHANGE消息。
接上一段当执行完PeerConnectionProxy::CreateOffer后,由于在Thread::Send的最后通过调用current_thread->socketserver()->WakeUp();,该函数即Win32SocketServer::WakeUp(),这个函数PostMessage(wnd_.handle(), s_wm_wakeup_id, 0, 0);,所以主线程中创建的Win32SocketServer对象的成员变量MessageWindow wnd_;会收到消息s_wm_wakeup_id,其实应该是主线程收到消息,因为主线程(即talk_base::Win32Thread w32_thread;)中创建了Win32SocketServer对象及其成员变量MessageWindow wnd_;,根据MSDN对PostMessage函数的解释"Places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message."。所以主线程的消息队列中收到s_wm_wakeup_id消息。这样说明了主线程通过Win32SocketServer::Wait函数的GetMessage(&msg, NULL, s_wm_wakeup_id, s_wm_wakeup_id);,而signaling_thread_线程通过Win32SocketServer::WakeUp函数中的PostMessage(wnd_.handle(), s_wm_wakeup_id, 0, 0);来唤醒,由于"函数GetMessage 是 从调用线程的消息队列里取得一个消息并将其放于指定的结构。GetMessage不接收属于其他线程或应用程序的消息。",但是通过PostMessage的MSDN注释可以明白子线程唤醒主线程。
而且在Conductor::ConnectToPeer函数中会调用主线程发送MSG_STATE_CHANGE消息,会唤醒一个主线程的等待,但是在主线程通过Thread::Send函数中的while循环判断当前的消息并没有被响应会继续阻塞,即主线程消耗掉了一次唤醒,这样当Thread::Send执行到最后,即当前消息发送的流程执行完之后需要再一次唤醒主线程(或者叫当前线程,因为这里是以主线程为例)。看一下Thread::Send函数最后的注释很详细。
以上是关于libjingle主线程的消息响应的主要内容,如果未能解决你的问题,请参考以下文章