参考:https://juejin.cn/post/6844904041835659277#comment
文章目录
- 创建Thread对象:
- Thread的Run()函数中:
- NullSocketServer中的事件:
- PhysicalSocketServer中的事件:
- Wait()函数:
- 什么时候唤醒线程?[此处指的是普通队列事件,socket事件的唤醒是看不到的]
- 一个demo:
创建Thread对象:
-
Thread继承MessageQueue
-
Thread提供两个静态方法,分别用来创建带socket和不带socket的线程:
static std::unique_ptr CreateWithSocketServer();
static std::unique_ptr Create();


Thread的Run()函数中:
void Thread::Run() {
ProcessMessages(kForever); //wgj 调用Thread的Start方法时,会调用Thread::ProcessMessages方法。
}
bool Thread::ProcessMessages(int cmsLoop) {
// Using ProcessMessages with a custom clock for testing and a time greater
// than 0 doesn't work, since it's not guaranteed to advance the custom
// clock's time, and may get stuck in an infinite loop.
RTC_DCHECK(GetClockForTesting() == nullptr || cmsLoop == 0 ||
cmsLoop == kForever);
int64_t msEnd = (kForever == cmsLoop) ? 0 : TimeAfter(cmsLoop);
int cmsNext = cmsLoop;
while (true) {
#if defined(WEBRTC_MAC)
ScopedAutoReleasePool pool;
#endif
Message msg;
if (!Get(&msg, cmsNext))//wgj 获取消息
return !IsQuitting();
Dispatch(&msg);//分发消息
if (cmsLoop != kForever) {
cmsNext = static_cast<int>(TimeUntil(msEnd));
if (cmsNext < 0)
return true;
}
}
}
bool MessageQueue::Get(Message* pmsg, int cmsWait, bool process_io) {
// Pull a message off the message queue, if available.
if (msgq_.empty()) {
break;
} else {
*pmsg = msgq_.front();
msgq_.pop_front(); //从消息队列中 拿一条消息出来
}
{
// Wait and multiplex in the meantime
if (!ss_->Wait(static_cast<int>(cmsNext), process_io)) //Get方法很关键,它获取消息队列中的message,如果MessageQueue有SocketServer对象,调用Wait方法,执行IO的读写操作。[此处可能是普通事件或者socket事件]
return false;
}
void MessageQueue::Dispatch(Message* pmsg) {
TRACE_EVENT2("webrtc", "MessageQueue::Dispatch", "src_file_and_line",
pmsg->posted_from.file_and_line(), "src_func",
pmsg->posted_from.function_name());
int64_t start_time = TimeMillis();
pmsg->phandler->OnMessage(pmsg);//wgj 注意pmsg->phandler 回调函数:MessageHandler的OnMessage方法
int64_t end_time = TimeMillis();
int64_t diff = TimeDiff(end_time, start_time);
if (diff >= kSlowDispatchLoggingThreshold) {
RTC_LOG(LS_INFO) << "Message took " << diff
<< "ms to dispatch. Posted from: "
<< pmsg->posted_from.ToString();
}
}
NullSocketServer中的事件:
linux:
关于wait()函数:在NullSocketServer中:
使用pthread_cond_wait条件变量,而在
void NullSocketServer::WakeUp() {
event_.Set();
}
中使用pthread_cond_signal();
windows:
而在windows上使用:
WaitForSingleObject和SetEvent
PhysicalSocketServer中的事件:
在PhysicalSocketServer构造函数中,包含普通事件和socket事件:
PhysicalSocketServer::PhysicalSocketServer() : fWait_(false) {
#if defined(WEBRTC_USE_EPOLL)
// Since Linux 2.6.8, the size argument is ignored, but must be greater than
// zero. Before that the size served as hint to the kernel for the amount of
// space to initially allocate in internal data structures.
epoll_fd_ = epoll_create(FD_SETSIZE);
if (epoll_fd_ == -1) {
// Not an error, will fall back to "select" below.
RTC_LOG_E(LS_WARNING, EN, errno) << "epoll_create";
epoll_fd_ = INVALID_SOCKET;
}
#endif
signal_wakeup_ = new Signaler(this, &fWait_); //wgj 普通事件 用于处理:消息队列
#if defined(WEBRTC_WIN)
socket_ev_ = WSACreateEvent();//wgj windows中的socket事件 用于处理:socket
#endif
}
在linux中的普通事件:
#if defined(WEBRTC_POSIX)
class EventDispatcher : public Dispatcher {
public:
EventDispatcher(PhysicalSocketServer* ss) : ss_(ss), fSignaled_(false) {
if (pipe(afd_) < 0) //wgj afd_是个有名管道
RTC_LOG(LERROR) << "pipe failed";
ss_->Add(this);
}
virtual void Signal() {
CritScope cs(&crit_);
if (!fSignaled_) {
const uint8_t b[1] = {0};
const ssize_t res = write(afd_[1], b, sizeof(b)); //wgj PhysicalSocketServer中有一个信号量Signaler(一个pipe),也被epoll管理。当有message加入消息队列时(一个List),信号量发送1个字节的数据,触发epoll的读事件,让线程继续运行。
RTC_DCHECK_EQ(1, res);
fSignaled_ = true;
}
}
windows中的普通事件:
class EventDispatcher : public Dispatcher {
public:
EventDispatcher(PhysicalSocketServer* ss) : ss_(ss) {
hev_ = WSACreateEvent(); //wgj 用于处理:消息队列
if (hev_) {
ss_->Add(this);
}
}
virtual void Signal() {
if (hev_ != nullptr)
WSASetEvent(hev_);
}
Wait()函数:
Windows中:
#if defined(WEBRTC_WIN)
bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
int64_t cmsTotal = cmsWait;
int64_t cmsElapsed = 0;
int64_t msStart = Time();
fWait_ = true;
while (fWait_) {
std::vector<WSAEVENT> events; //所有事件
std::vector<Dispatcher*> event_owners; //只有普通事件
events.push_back(socket_ev_);
{
CritScope cr(&crit_);
// TODO(jbauch): Support re-entrant waiting.
RTC_DCHECK(!processing_dispatchers_);
// Calling "CheckSignalClose" might remove a closed dispatcher from the
// set. This must be deferred to prevent invalidating the iterator.
processing_dispatchers_ = true;
for (Dispatcher* disp : dispatchers_) {
if (!process_io && (disp != signal_wakeup_))
continue;
SOCKET s = disp->GetSocket();
if (disp->CheckSignalClose()) {
// We just signalled close, don't poll this socket
} else if (s != INVALID_SOCKET) {
WSAEventSelect(s, events[0],//wgj socket事件
FlagsToEvents(disp->GetRequestedEvents()));
} else {
events.push_back(disp->GetWSAEvent());//普通事件
event_owners.push_back(disp);
}
}
processing_dispatchers_ = false;
// Process deferred dispatchers that have been added/removed while the
// events were handled above.
AddRemovePendingDispatchers();
}
// Which is shorter, the delay wait or the asked wait?
int64_t cmsNext;
if (cmsWait == kForever) {
cmsNext = cmsWait;
} else {
cmsNext = std::max<int64_t>(0, cmsTotal - cmsElapsed);
}
// Wait for one of the events to signal
DWORD dw =
WSAWaitForMultipleEvents(static_cast<DWORD>(events.size()), &events[0],//wgj 类似WaitForMultipleObjects()
false, static_cast<DWORD>(cmsNext), false);
if (dw == WSA_WAIT_FAILED) {
// Failed?
// TODO(pthatcher): need a better strategy than this!
WSAGetLastError();
RTC_NOTREACHED();
return false;
} else if (dw == WSA_WAIT_TIMEOUT) {
// Timeout?
return true;
} else {
// Figure out which one it is and call it
CritScope cr(&crit_);
int index = dw - WSA_WAIT_EVENT_0;
if (index > 0) {//普通事件
--index; // The first event is the socket event
Dispatcher* disp = event_owners[index];
// The dispatcher could have been removed while waiting for events.
if (dispatchers_.find(disp) != dispatchers_.end()) {
disp->OnPreEvent(0);
disp->OnEvent(0, 0);
}
} else if (process_io) {//socket事件
processing_dispatchers_ = true;
for (Dispatcher* disp : dispatchers_) {
SOCKET s = disp->GetSocket();
if (s == INVALID_SOCKET)
continue;
WSANETWORKEVENTS wsaEvents;
int err = WSAEnumNetworkEvents(s, events[0], &wsaEvents); //注意:此处是涉及socket的部分
if (err == 0) {
{
if ((wsaEvents.lNetworkEvents & FD_READ) &&
wsaEvents.iErrorCode[FD_READ_BIT] != 0) {
RTC_LOG(WARNING)
<< "PhysicalSocketServer got FD_READ_BIT error "
<< wsaEvents.iErrorCode[FD_READ_BIT];
}
if ((wsaEvents.lNetworkEvents & FD_WRITE) &&
wsaEvents.iErrorCode[FD_WRITE_BIT] != 0) {
RTC_LOG(WARNING)
<< "PhysicalSocketServer got FD_WRITE_BIT error "
<< wsaEvents.iErrorCode[FD_WRITE_BIT];
}
if ((wsaEvents.lNetworkEvents & FD_CONNECT) &&
wsaEvents.iErrorCode[FD_CONNECT_BIT] != 0) {
RTC_LOG(WARNING)
<< "PhysicalSocketServer got FD_CONNECT_BIT error "
<< wsaEvents.iErrorCode[FD_CONNECT_BIT];
}
if ((wsaEvents.lNetworkEvents & FD_ACCEPT) &&
wsaEvents.iErrorCode[FD_ACCEPT_BIT] != 0) {
RTC_LOG(WARNING)
<< "PhysicalSocketServer got FD_ACCEPT_BIT error "
<< wsaEvents.iErrorCode[FD_ACCEPT_BIT];
}
if ((wsaEvents.lNetworkEvents & FD_CLOSE) &&
wsaEvents.iErrorCode[FD_CLOSE_BIT] != 0) {
RTC_LOG(WARNING)
<< "PhysicalSocketServer got FD_CLOSE_BIT error "
<< wsaEvents.iErrorCode[FD_CLOSE_BIT];
}
}
uint32_t ff = 0;
int errcode = 0;
if (wsaEvents.lNetworkEvents & FD_READ)
ff |= DE_READ;
if (wsaEvents.lNetworkEvents & FD_WRITE)
ff |= DE_WRITE;
if (wsaEvents.lNetworkEvents & FD_CONNECT) {
if (wsaEvents.iErrorCode[FD_CONNECT_BIT] == 0) {
ff |= DE_CONNECT;
} else {
ff |= DE_CLOSE;
errcode = wsaEvents.iErrorCode[FD_CONNECT_BIT];
}
}
if (wsaEvents.lNetworkEvents & FD_ACCEPT)
ff |= DE_ACCEPT;
if (wsaEvents.lNetworkEvents & FD_CLOSE) {
ff |= DE_CLOSE;
errcode = wsaEvents.iErrorCode[FD_CLOSE_BIT];
}
if (ff != 0) {
disp->OnPreEvent(ff);
disp->OnEvent(ff, errcode); //注意:此处是涉及socket的部分
}
}
}
processing_dispatchers_ = false;
// Process deferred dispatchers that have been added/removed while the
// events were handled above.
AddRemovePendingDispatchers();
}
// Reset the network event until new activity occurs
WSAResetEvent(socket_ev_);
}
// Break?
if (!fWait_)
break;
cmsElapsed = TimeSince(msStart);
if ((cmsWait != kForever) && (cmsElapsed >= cmsWait)) {
break;
}
}
// Done
return true;
}
#endif // WEBRTC_WIN
Linux中:
bool PhysicalSocketServer::Wait(int cmsWait, bool process_io) {
else if (epoll_fd_ != INVALID_SOCKET) {
return WaitEpoll(cmsWait);//wgj epoll
bool PhysicalSocketServer::WaitEpoll(int cmsWait) {
int n = epoll_wait(epoll_fd_, &epoll_events_[0],
static_cast<int>(epoll_events_.size()),
static_cast<int>(tvWait)); //wgj
什么时候唤醒线程?[此处指的是普通队列事件,socket事件的唤醒是看不到的]
MessageQueue::Post方法也很重要,用于向消息队列中添加消息。
struct Message {
Message()
: phandler(nullptr), message_id(0), pdata(nullptr), ts_sensitive(0) {}
inline bool Match(MessageHandler* handler, uint32_t id) const {
return (handler == nullptr || handler == phandler) &&
(id == MQID_ANY || id == message_id);
}
Location posted_from;
MessageHandler* phandler;
uint32_t message_id;
MessageData* pdata;
int64_t ts_sensitive;
};
void MessageQueue::Post(const Location& posted_from,
MessageHandler* phandler,
uint32_t id,
MessageData* pdata,
bool time_sensitive) {
if (IsQuitting()) {
delete pdata;
return;
}
// Keep thread safe
// Add the message to the end of the queue
// Signal for the multiplexer to return
{
CritScope cs(&crit_);
Message msg;
msg.posted_from = posted_from;
msg.phandler = phandler;
msg.message_id = id;
msg.pdata = pdata;
if (time_sensitive) {
msg.ts_sensitive = TimeMillis() + kMaxMsgLatency;
}
msgq_.push_back(msg);
}
WakeUpSocketServer(); //wgj
}
class MessageHandler {
public:
virtual ~MessageHandler();
virtual void OnMessage(Message* msg) = 0;
protected:
MessageHandler() {}
private:
RTC_DISALLOW_COPY_AND_ASSIGN(MessageHandler);
};
一个demo:
#include <iostream>
#include "rtc_base/thread.h"
#include "rtc_base/async_invoker.h"
#include "rtc_base/event.h"
#include "rtc_base/null_socket_server.h"
#include "rtc_base/physical_socket_server.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/third_party/sigslot/sigslot.h"
#include "rtc_base/async_udp_socket.h"
using namespace std;
using namespace rtc;
struct MyMessage : public MessageData {
explicit MyMessage(int v) : value(v) {}
int value;
};
class Client : public MessageHandler,public sigslot::has_slots<> {
public:
Client(AsyncUDPSocket* socket,Thread * thread) : socket_(socket),thread_(thread) {
// 用到了webrtc的sigslot,需要专门写篇文章。
// 简单理解:OnPacket注册为socket的数据读取回调。
socket_->SignalReadPacket.connect(this, &Client::OnPacket);
}
~Client() {
delete socket_;
}
// 消息队列中,消息触发后的回调。
void OnMessage(Message* pmsg) override {
MyMessage* msg = static_cast<MyMessage*>(pmsg->pdata);
PacketOptions opt;
socket_->Send(&msg->value, sizeof(msg->value),opt);
delete msg;
}
void OnPacket(AsyncPacketSocket* socket,
const char* buf,
size_t size,
const SocketAddress& remote_addr,
const int64_t& packet_time_us) {
uint32_t data = reinterpret_cast<const uint32_t*>(buf)[0];
cout << "---Recv server data:"<<data<<endl;
data++;
// 收到服务端的消息,累加后,继续发送给服务端
thread_->PostDelayed(RTC_FROM_HERE, 2000, this, 0,new MyMessage(data));
}
private:
AsyncUDPSocket* socket_;
Thread * thread_;
};
class Server : public MessageHandler,public sigslot::has_slots<> {
public:
Server(AsyncUDPSocket* socket,Thread * thread) : socket_(socket),thread_(thread) {
socket_->SignalReadPacket.connect(this, &Server::OnPacket);
}
~Server() {
delete socket_;
}
void OnMessage(Message* pmsg) override {
MyMessage* msg = static_cast<MyMessage*>(pmsg->pdata);
PacketOptions opt;
socket_->SendTo(&msg->value, sizeof(msg->value),remote_addr_,opt);
delete msg;
}
void OnPacket(AsyncPacketSocket* socket,
const char* buf,
size_t size,
const SocketAddress& remote_addr,
const int64_t& packet_time_us) {
remote_addr_=remote_addr;
uint32_t data = reinterpret_cast<const uint32_t*>(buf)[0];
cout << "---Recv client data:"<<data<<"|"<<remote_addr_.ToString()<<endl;
data++;
// 收到客户端的消息,累加后,继续发送给客户端
thread_->PostDelayed(RTC_FROM_HERE, 2000, this, 0,new MyMessage(data));
}
private:
AsyncUDPSocket* socket_;
Thread * thread_;
SocketAddress remote_addr_;
};
int main(){
// 客户端
SocketAddress addr1("0.0.0.0", 7000);
std::unique_ptr<Thread> th1=Thread::CreateWithSocketServer();
AsyncSocket* sock1 = th1->socketserver()->CreateAsyncSocket(addr1.family(), SOCK_DGRAM);
AsyncUDPSocket * clientSock=AsyncUDPSocket::Create(sock1, addr1);
Client client(clientSock,th1.get());
// 服务端
SocketAddress addr2("0.0.0.0", 7001);
std::unique_ptr<Thread> th2=Thread::CreateWithSocketServer();
AsyncSocket* sock2 = th2->socketserver()->CreateAsyncSocket(addr2.family(), SOCK_DGRAM);
AsyncUDPSocket * serverSock=AsyncUDPSocket::Create(sock2, addr2);
Server server(serverSock,th2.get());
sock1->Connect(serverSock->GetLocalAddress());
th1->Start();
th2->Start();
// 触发终端发数据,向线程的消息队列添加Message
th1->PostDelayed(RTC_FROM_HERE, 1000, &client, 0, new MyMessage(1));
// 主线程,无限循环,避免程序退出
Thread::Current()->ProcessMessages(-1);
return 0;
}