阅读时 Chrome版本: 75.0.3770.4
标记方法:
下划线为当前函数归属类。
A,b代表变量b,类型为A。
斜体代表特殊名词。
拥有:指控制对象的生命周期。
终端,端点:endpoint。
消息管道: message pipe。
消息:message。
任务:tasks。
粗体代表函数名。
Foo::Bar。
删除线代表已经废弃。
ReadSingleMessage,此函数在上一个正式版中存在,此版本中已废弃。
方括号代表可能出现的步骤。
[7-1.] 第7步在某些特殊情况下会调用到此分支。
[7-b-1.] 第7步在某些特殊情况下会调用到此分支[7-b],在此之前还有一个并列的分支[7-a]。
本文由@leonwxqian (各社交媒体同号)编写。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1. base::`anonymous namespace'::ThreadFunc
做简单初始化后,调用delegate->ThreadMain()。
delegate为PlatformThread::Delegate*,值为thread_params->delegate。
thread_params类型为ThreadParams。由CreateThread传递来的参数直接转换。最终delegate即为Thread对象。
2. base::Thread::ThreadMain
在这一层初始化线程环境,并创建RunLoop run_loop对象,然后通过Run(run_loop_)传递给下一层。
3. content::BrowserProcessSubThread::Run
根据三种情况调用不同的函数:
BrowserThread::UI | UIThreadRun(run_loop) |
BrowserThread::IO | IOThreadRun(run_loop) |
BrowserThread::ID_COUNT | 未实现 |
4. content::BrowserProcessSubThread::IOThreadRun
直接调用Thread::Run(run_loop)。run_loop由上层传递而来。
5. base::Thread::Run
由ServiceThread::Run或BrowserProcessSubThread::IOThreadRun创建。我们只关心后面的情况。直接调用run_loop->Run()。
run_loop即为RunLoop的实例。由[2]创建。
6. base::RunLoop::Run
调用RunWithTimeout(TimeDelta::Max())。即不限时长地运行。
在RunWithTimeout中,调用delegate_->Run。
同样,delegate_在RunLoop::RunLoop构造时就会被初始化成tls_delegate.Get().Get()。即MessageLoop。
7. base::MessageLoop::Run
调用对应系统的Run操作。
8. base::MessagePump[System]::Run
简单初始化后直接调用DoRunLoop()。
9. base::MessagePumpForIO::DoRunLoop
消息循环中依次调用:
state_->delegate->DoSomeWork()、WaitForIOCompletion、state_->delegate->DoIdleWork()。我们只看第二种情况。
10. base::MessagePumpForIO::WaitForIOCompletion
一直等待系统,直到IO完成。
如果消息已经完成,调用item.handler->OnIOCompleted。
item的定义为IOItem。IOItem是一个结构体,它在MessagePumpForIO::GetIOItem处被GetQueuedCompletionStatus初始化。这是一个和系统绑定的对象。具体见下一个调用。
11. mojo::core::`anonymous namespace'::Channel[System]::OnIOCompleted
此类根据系统不同而名称不同。
但是动作一致,都是在IO动作完成后,如果是读动作,则调用OnReadDone并进一步触发OnReadComplete。
如果是写动作,则调用OnWriteDone并进一步触发OnWriteComplete。
12. mojo::core::Channel::OnReadComplete
当管道中消息大于消息头大小时,开始尝试读取头。
若消息数据不是对齐的,则试图重新对齐,以防在非x86架构上出现SIGBUS错误。
读取后,调用TryDispatchMessage来尝试分发消息。
13. mojo::core::Channel::TryDispatchMessage
校验消息合法性(头大小、载荷大小、载荷句柄数量),如果消息合法,则试图分发。
如果是控制消息,则转发到OnControlMessage。
如果是已经不再需要的消息,则直接丢弃。
如果是其他消息,则发送到delegate_->OnChannelMessage。
14. mojo::core::NodeChannel::OnChannelMessage
该函数进入时则创建RequestContext request_context(RequestContext::Source::SYSTEM)。
该函数处理多种节点消息,分别如下:
MessageType::ACCEPT_INVITEE | 处理被邀请的对象 | |
MessageType::ACCEPT_INVITATION | 处理邀请 | |
MessageType::ADD_BROKER_CLIENT | 添加代理客户端 | |
MessageType::BROKER_CLIENT_ADDED | 代理客户端已添加 | |
MessageType::ACCEPT_BROKER_CLIENT | 处理代理客户端 | |
MessageType::EVENT_MESSAGE | 事件消息 | |
MessageType::REQUEST_PORT_MERGE | 请求端口合并 | |
MessageType::REQUEST_INTRODUCTION | 请求详情 | |
MessageType::INTRODUCE | 详情消息 | |
MessageType::RELAY_EVENT_MESSAGE | WIN 或 MAC OS (不包含iOS) | 续传事件消息 |
MessageType::BROADCAST_EVENT | 广播事件消息 | |
MessageType::EVENT_MESSAGE_FROM_RELAY | WIN 或 MAC OS (不包含iOS) | 来自续传事件的消息 |
MessageType::ACCEPT_PEER | 处理节点 |
函数会根据节点类型调用对应的delegate_->OnXXXXX()函数。NodeChannel::NodeChannel初始化时即构造了delegate_。
动作通常由NodeChannel::Create完成。一些特殊类型的消息,例如Introduce,会在OnIntroduce中调用Create,并将NodeController添加为delegate_。 |
不过,如果消息不属于上述任何一个类型,函数将会退出。但是退出时会析构RequestContext。
在RequestContext::~RequestContext中,如果有Watch挂在当前Context下,它会先依次创建RequestContext对象,并借由它清空所有Watch(通过发送MOJO_RESULT_CANCELLED)。然后再对所有需要通知的Watch(watch_notify_finalizers_)调用watch.watch->InvokeCallback。
15. mojo::core::Watch::InvokeCallback
如果消息没有取消,则调用watcher_->InvokeWatchCallback。在Watch::Watch构造时,const scoped_refptr<WatcherDispatcher> ,watcher_即被初始化。
通常,这是在调用WatcherDispatcher::WatchDispatcher时,通过将this传入Watch的构造函数来完成的。 所以,下一步即调用mojo::core::WatcherDispatcher::InvokeWatchCallback。 |
16. mojo::core::WatcherDispatcher::InvokeWatchCallback
根据调入的参数,构造一个MojoTrapEvent对象,并调用handler_(&event)。handler_的定义为const MojoTrapEventHandler。在构造WatcherDispatcher时,handler_就会被初始化。
通常,这是在调用Core::CreateTrap时,新建一个Trap,并加入传入的handle从而初始化的。 在SimpleWatcher::SimpleWatcher处,MojoResult rv = CreateTrap(&Context::CallNotify, &trap_handle_); 通过该语句将自己注册成Trap Handler。 所以在本例中,下一步即调用 mojo::SimpleWatcher::Context::CallNotify。 |
N. 后置逻辑