所谓的消息嵌套,说白了,就类似函数递归。下面存在这样一种场景,会导致所谓的嵌套发生。
需要解决一种使用场景,例如主线程post一个任务到MessageLoop的队列中,然后调用MessageLoop::Run。
这是进入消息处理,而这个抛入的任务实际上做的也是调用MessageLoop::Run。
那这就陷入了2个问题
1,要么出现多次“嵌套”,直到最后一个待处理的任务被执行完,然后再逐级返回,以至于最后一个任务被处理完。
2,要么直接死循环或者说是饿死。因为有可能抛入的任务都是调用同一个线程的MessageLoop::Run,然后最后被处理的任务被停在了事件等待上面,这个事件是用于等待有新MessageLoop任务抛入的。
因此nestable_tasks_allowed_ 标记就成了关键,这个标记控制着不允许任务会被嵌套的情况发生。
代码如下
MessageLoop* task_run_on = NULL;
MessageLoop* task_deleted_on = NULL;
int task_delete_order = -1;
MessageLoop* reply_run_on = NULL;
MessageLoop* reply_deleted_on = NULL;
int reply_delete_order = -1;
scoped_refptr task_recoder =
new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
scoped_refptr reply_recoder =
new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
ASSERT_TRUE(task_thread_.message_loop_proxy()->PostTaskAndReply(
FROM_HERE,
Bind(&RecordLoop, task_recoder),
Bind(&RecordLoopAndQuit, reply_recoder)));
// Die if base::Bind doesn't retain a reference to the recorders.
task_recoder = NULL;
reply_recoder = NULL;
ASSERT_FALSE(task_deleted_on);
ASSERT_FALSE(reply_deleted_on);
//--- 这里将是比较关键的一个问题 begin ---
UnblockTaskThread();
current_loop_->Run();
//--- 这里将是比较关键的一个问题 end ---
EXPECT_EQ(task_thread_.message_loop(), task_run_on);
EXPECT_EQ(current_loop_.get(), task_deleted_on);
EXPECT_EQ(current_loop_.get(), reply_run_on);
EXPECT_EQ(current_loop_.get(), reply_deleted_on);
EXPECT_LT(task_delete_order, reply_delete_order);
readmore