本文由@leonwxqian (各社交媒体同号)编写。
阅读时 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]。
0. 前置逻辑
前置仍然有许多逻辑,下一篇再看吧。
1. mojo::SimpleWatcher::Context::CallNotify
获取MojoTrapEvent的Context,并调用其Notify函数。
在SimpleWatcher构造时,TrapEvent的上下文即被设置为Context::CallNotify。
所以这里调用的即SimpleWatcher::Context::Notify。
2. mojo::SimpleWatcher::Context::Notify
如果消息未被取消,则继续发送消息。
根据不同的设置来确认是从base::WeakPtr<SimpleWatcher>,Weakptr指向的内容直接调用OnHandleReady还是PostTask去调用SimpleWatcher::OnHandleReady。
我们只关心后面的情况。
3. mojo::SimpleWatcher::OnHandleReady
如果消息已经是取消状态,则不做任何事。
如果有回调,则调用该回调。ReadyCallbackWithState,callback指向callback_。
ReadyCallbackWithState是一个语法糖,实际为 base::RepeatingCallback<void(MojoResult result, const HandleSignalsState& state)>。
在mojo::SimpleWatcher::Watch时,callback_就会被设置上。
[3-1.]. mojo::Connector::Connector
会调用WaitToReadMore。
[3-2.]. mojo::Connector::WaitToReadMore 或 mojo::Connector::EnsureSyncWatcherExists
会创建mojo::Connector::OnWatcherHandleReady 或 mojo::Connector::OnSyncHandleWatcherHandleReady。
我们现在只关心前一种情况。
WaitToReadMore调用Watch,即handle_watcher_->Watch,绑定Connector::OnWatcherHandleReady。
[3-3. ]. mojo::Connector::OnWatcherHandleReady 或 mojo::Connector::OnSyncHandleWatcherHandleReady
都会通知到OnHandleReadyInternal。
这样,这里的回调,相当于就通知到了OnWatcherHandleReady ,随后调用 OnHandleReadyInternal。
4. mojo::Connector::OnHandleReadyInternal
如果获得通知时mojo的状态正确,则调用ReadAllAvailableMessages来处理消息。
5. mojo::Connector::ReadAllAvailableMessages
调用[5-1.]ReadMessage从消息管道中获取消息,如果该消息是消息队列中的第一个消息,或者标记为需要立刻发送。则调用DispatchMessage立刻分发该消息。
否则,向base::queue<Message>,dispatch_queue_中推送该消息。dispatch_queue_代表所有已经读取但是没有处理的消息。
调用PostTask向任务队列上推送对此消息的处理,绑定的函数是Connector::DispatchNextMessageInQueue。
[5-1. ]. mojo::Connector::ReadMessage
在早期版本中此函数叫ReadSingleMessage。
从消息管道中取出一个消息,然后创建一个Message对象。
当创建失败时返回异常(NotifyBadMessage)。
6. mojo::Connector::DispatchNextMessageInQueue
调用DispatchMessage来处理消息。
7. mojo::Connector::DispatchMessage
调用incoming_receiver_->Accept(&message)来处理消息。通常,在MultiplexRouter构造时会调用connector_.set_incoming_receiver(&filters_);将自己的std::vector<std::unique_ptr<MessageReceiver>>,filters_注册为incoming_receiver_。
8. mojo::internal::MultiplexRouter::Accept
异步和同步消息都会走到这里,为了防止阻塞导致的问题,程序会在Accept的第一时间就调用MultiplexRouter::InsertEndpointsForMessage将数据插入到消息关联的端点列表中。
- 如果base::circular_deque<std::unique_ptr<Task>>,tasks_目前为空,代表无待处理的消息,则转发消息到MultiplexRouter::ProcessIncomingMessage中开始处理消息。
- 如果任务失败或tasks_不为空,则将消息封装塞入tasks_,如果此task还有同步标志,则向std::map<InterfaceId, base::circular_deque<Task*>>, sync_message_tasks_[id](id为InterfaceId)中也推送task,并通知端点。sync_message_tasks_只保留指针副本,不拥有指针对象。
- 如果任务成功执行,但是执行的过程中又产生了新消息(如抛出异常),导致tasks_不再为空,则程序再次调用ProcessTasks处理这个任务。
[8-1. ] MultiplexRouter::ProcessTasks
如果当前任务是异常通知任务,则调用ProcessNotifyErrorTask。否则调用ProcessIncomingMessage来处理消息。
在完成后会清理掉消息。如果此消息仍未被处理,则把它推到tasks_的最前端,在下一个循环中继续执行。
N. 后置逻辑