Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/message_loop/message_loop_task_runner.h" | 5 #include "base/message_loop/message_loop_task_runner.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/atomic_sequence_num.h" | 9 #include "base/atomic_sequence_num.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 101 StaticAtomicSequenceNumber MessageLoopTaskRunnerTest::g_order; | 101 StaticAtomicSequenceNumber MessageLoopTaskRunnerTest::g_order; |
| 102 | 102 |
| 103 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_Basic) { | 103 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_Basic) { |
| 104 MessageLoop* task_run_on = NULL; | 104 MessageLoop* task_run_on = NULL; |
| 105 MessageLoop* task_deleted_on = NULL; | 105 MessageLoop* task_deleted_on = NULL; |
| 106 int task_delete_order = -1; | 106 int task_delete_order = -1; |
| 107 MessageLoop* reply_run_on = NULL; | 107 MessageLoop* reply_run_on = NULL; |
| 108 MessageLoop* reply_deleted_on = NULL; | 108 MessageLoop* reply_deleted_on = NULL; |
| 109 int reply_delete_order = -1; | 109 int reply_delete_order = -1; |
| 110 | 110 |
| 111 scoped_refptr<LoopRecorder> task_recoder = | 111 scoped_refptr<LoopRecorder> task_recorder = |
| 112 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); | 112 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); |
| 113 scoped_refptr<LoopRecorder> reply_recoder = | 113 scoped_refptr<LoopRecorder> reply_recorder = |
| 114 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); | 114 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); |
| 115 | 115 |
| 116 ASSERT_TRUE(task_thread_.task_runner()->PostTaskAndReply( | 116 ASSERT_TRUE(task_thread_.task_runner()->PostTaskAndReply( |
| 117 FROM_HERE, Bind(&RecordLoop, task_recoder), | 117 FROM_HERE, Bind(&RecordLoop, task_recorder), |
| 118 Bind(&RecordLoopAndQuit, reply_recoder))); | 118 Bind(&RecordLoopAndQuit, reply_recorder))); |
| 119 | 119 |
| 120 // Die if base::Bind doesn't retain a reference to the recorders. | 120 // Die if base::Bind doesn't retain a reference to the recorders. |
| 121 task_recoder = NULL; | 121 task_recorder = NULL; |
| 122 reply_recoder = NULL; | 122 reply_recorder = NULL; |
| 123 ASSERT_FALSE(task_deleted_on); | 123 ASSERT_FALSE(task_deleted_on); |
| 124 ASSERT_FALSE(reply_deleted_on); | 124 ASSERT_FALSE(reply_deleted_on); |
| 125 | 125 |
| 126 UnblockTaskThread(); | 126 UnblockTaskThread(); |
| 127 RunLoop().Run(); | 127 RunLoop().Run(); |
| 128 | 128 |
| 129 EXPECT_EQ(task_thread_.message_loop(), task_run_on); | 129 EXPECT_EQ(task_thread_.message_loop(), task_run_on); |
| 130 EXPECT_EQ(current_loop_.get(), task_deleted_on); | 130 EXPECT_EQ(task_thread_.message_loop(), task_deleted_on); |
| 131 EXPECT_EQ(current_loop_.get(), reply_run_on); | 131 EXPECT_EQ(current_loop_.get(), reply_run_on); |
| 132 EXPECT_EQ(current_loop_.get(), reply_deleted_on); | 132 EXPECT_EQ(current_loop_.get(), reply_deleted_on); |
| 133 EXPECT_LT(task_delete_order, reply_delete_order); | 133 EXPECT_LT(task_delete_order, reply_delete_order); |
| 134 } | 134 } |
| 135 | 135 |
| 136 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) { | 136 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) { |
| 137 MessageLoop* task_run_on = NULL; | 137 MessageLoop* task_run_on = NULL; |
| 138 MessageLoop* task_deleted_on = NULL; | 138 MessageLoop* task_deleted_on = NULL; |
| 139 int task_delete_order = -1; | 139 int task_delete_order = -1; |
| 140 MessageLoop* reply_run_on = NULL; | 140 MessageLoop* reply_run_on = NULL; |
| 141 MessageLoop* reply_deleted_on = NULL; | 141 MessageLoop* reply_deleted_on = NULL; |
| 142 int reply_delete_order = -1; | 142 int reply_delete_order = -1; |
| 143 | 143 |
| 144 scoped_refptr<LoopRecorder> task_recoder = | 144 scoped_refptr<LoopRecorder> task_recorder = |
| 145 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); | 145 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); |
| 146 scoped_refptr<LoopRecorder> reply_recoder = | 146 scoped_refptr<LoopRecorder> reply_recorder = |
| 147 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); | 147 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); |
| 148 | 148 |
| 149 // Grab a task runner to a dead MessageLoop. | 149 // Grab a task runner to a dead MessageLoop. |
| 150 scoped_refptr<SingleThreadTaskRunner> task_runner = | 150 scoped_refptr<SingleThreadTaskRunner> task_runner = |
| 151 task_thread_.task_runner(); | 151 task_thread_.task_runner(); |
| 152 UnblockTaskThread(); | 152 UnblockTaskThread(); |
| 153 task_thread_.Stop(); | 153 task_thread_.Stop(); |
| 154 | 154 |
| 155 ASSERT_FALSE( | 155 ASSERT_FALSE( |
| 156 task_runner->PostTaskAndReply(FROM_HERE, Bind(&RecordLoop, task_recoder), | 156 task_runner->PostTaskAndReply(FROM_HERE, Bind(&RecordLoop, task_recorder), |
| 157 Bind(&RecordLoopAndQuit, reply_recoder))); | 157 Bind(&RecordLoopAndQuit, reply_recorder))); |
| 158 | 158 |
| 159 // The relay should have properly deleted its resources leaving us as the only | 159 // The relay should have properly deleted its resources leaving us as the only |
| 160 // reference. | 160 // reference. |
| 161 EXPECT_EQ(task_delete_order, reply_delete_order); | 161 EXPECT_EQ(task_delete_order, reply_delete_order); |
| 162 ASSERT_TRUE(task_recoder->HasOneRef()); | 162 ASSERT_TRUE(task_recorder->HasOneRef()); |
| 163 ASSERT_TRUE(reply_recoder->HasOneRef()); | 163 ASSERT_TRUE(reply_recorder->HasOneRef()); |
| 164 | 164 |
| 165 // Nothing should have run though. | 165 // Nothing should have run though. |
| 166 EXPECT_FALSE(task_run_on); | 166 EXPECT_FALSE(task_run_on); |
| 167 EXPECT_FALSE(reply_run_on); | 167 EXPECT_FALSE(reply_run_on); |
| 168 } | 168 } |
| 169 | 169 |
| 170 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_SameLoop) { | 170 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_SameLoop) { |
| 171 MessageLoop* task_run_on = NULL; | 171 MessageLoop* task_run_on = NULL; |
| 172 MessageLoop* task_deleted_on = NULL; | 172 MessageLoop* task_deleted_on = NULL; |
| 173 int task_delete_order = -1; | 173 int task_delete_order = -1; |
| 174 MessageLoop* reply_run_on = NULL; | 174 MessageLoop* reply_run_on = NULL; |
| 175 MessageLoop* reply_deleted_on = NULL; | 175 MessageLoop* reply_deleted_on = NULL; |
| 176 int reply_delete_order = -1; | 176 int reply_delete_order = -1; |
| 177 | 177 |
| 178 scoped_refptr<LoopRecorder> task_recoder = | 178 scoped_refptr<LoopRecorder> task_recorder = |
| 179 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); | 179 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); |
| 180 scoped_refptr<LoopRecorder> reply_recoder = | 180 scoped_refptr<LoopRecorder> reply_recorder = |
| 181 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); | 181 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); |
| 182 | 182 |
| 183 // Enqueue the relay. | 183 // Enqueue the relay. |
| 184 ASSERT_TRUE(current_loop_->task_runner()->PostTaskAndReply( | 184 ASSERT_TRUE(current_loop_->task_runner()->PostTaskAndReply( |
| 185 FROM_HERE, Bind(&RecordLoop, task_recoder), | 185 FROM_HERE, Bind(&RecordLoop, task_recorder), |
| 186 Bind(&RecordLoopAndQuit, reply_recoder))); | 186 Bind(&RecordLoopAndQuit, reply_recorder))); |
| 187 | 187 |
| 188 // Die if base::Bind doesn't retain a reference to the recorders. | 188 // Die if base::Bind doesn't retain a reference to the recorders. |
| 189 task_recoder = NULL; | 189 task_recorder = NULL; |
| 190 reply_recoder = NULL; | 190 reply_recorder = NULL; |
| 191 ASSERT_FALSE(task_deleted_on); | 191 ASSERT_FALSE(task_deleted_on); |
| 192 ASSERT_FALSE(reply_deleted_on); | 192 ASSERT_FALSE(reply_deleted_on); |
| 193 | 193 |
| 194 RunLoop().Run(); | 194 RunLoop().Run(); |
| 195 | 195 |
| 196 EXPECT_EQ(current_loop_.get(), task_run_on); | 196 EXPECT_EQ(current_loop_.get(), task_run_on); |
| 197 EXPECT_EQ(current_loop_.get(), task_deleted_on); | 197 EXPECT_EQ(current_loop_.get(), task_deleted_on); |
| 198 EXPECT_EQ(current_loop_.get(), reply_run_on); | 198 EXPECT_EQ(current_loop_.get(), reply_run_on); |
| 199 EXPECT_EQ(current_loop_.get(), reply_deleted_on); | 199 EXPECT_EQ(current_loop_.get(), reply_deleted_on); |
| 200 EXPECT_LT(task_delete_order, reply_delete_order); | 200 EXPECT_LT(task_delete_order, reply_delete_order); |
| 201 } | 201 } |
| 202 | 202 |
| 203 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) { | 203 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) { |
|
gab
2017/01/31 19:34:59
Rename
dcheng
2017/02/07 07:28:44
Per gab's comment, how about naming this: PostTask
tzik
2017/02/07 08:05:34
Done.
tzik
2017/02/07 08:05:34
Acknowledged.
tzik
2017/02/07 08:33:26
Done.
| |
| 204 // Annotate the scope as having memory leaks to suppress heapchecker reports. | 204 // Annotate the scope as having memory leaks to suppress heapchecker reports. |
| 205 ANNOTATE_SCOPED_MEMORY_LEAK; | 205 ANNOTATE_SCOPED_MEMORY_LEAK; |
| 206 MessageLoop* task_run_on = NULL; | 206 MessageLoop* task_run_on = NULL; |
| 207 MessageLoop* task_deleted_on = NULL; | 207 MessageLoop* task_deleted_on = NULL; |
| 208 int task_delete_order = -1; | 208 int task_delete_order = -1; |
| 209 MessageLoop* reply_run_on = NULL; | 209 MessageLoop* reply_run_on = NULL; |
| 210 MessageLoop* reply_deleted_on = NULL; | 210 MessageLoop* reply_deleted_on = NULL; |
| 211 int reply_delete_order = -1; | 211 int reply_delete_order = -1; |
| 212 | 212 |
| 213 scoped_refptr<LoopRecorder> task_recoder = | 213 scoped_refptr<LoopRecorder> task_recorder = |
| 214 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); | 214 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); |
| 215 scoped_refptr<LoopRecorder> reply_recoder = | 215 scoped_refptr<LoopRecorder> reply_recorder = |
| 216 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); | 216 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); |
| 217 | 217 |
| 218 // Enqueue the relay. | 218 // Enqueue the relay. |
| 219 task_thread_.task_runner()->PostTaskAndReply( | 219 task_thread_.task_runner()->PostTaskAndReply( |
| 220 FROM_HERE, Bind(&RecordLoop, task_recoder), | 220 FROM_HERE, Bind(&RecordLoop, task_recorder), |
| 221 Bind(&RecordLoopAndQuit, reply_recoder)); | 221 Bind(&RecordLoopAndQuit, reply_recorder)); |
| 222 | 222 |
| 223 // Die if base::Bind doesn't retain a reference to the recorders. | 223 // Die if base::Bind doesn't retain a reference to the recorders. |
| 224 task_recoder = NULL; | 224 task_recorder = NULL; |
| 225 reply_recoder = NULL; | 225 reply_recorder = NULL; |
| 226 ASSERT_FALSE(task_deleted_on); | 226 ASSERT_FALSE(task_deleted_on); |
| 227 ASSERT_FALSE(reply_deleted_on); | 227 ASSERT_FALSE(reply_deleted_on); |
| 228 | 228 |
| 229 UnblockTaskThread(); | 229 UnblockTaskThread(); |
| 230 | 230 |
| 231 // Mercilessly whack the current loop before |reply| gets to run. | 231 // Mercilessly whack the current loop before |reply| gets to run. |
| 232 current_loop_.reset(); | 232 current_loop_.reset(); |
| 233 | 233 |
| 234 // This should ensure the relay has been run. We need to record the | 234 // This should ensure the relay has been run. We need to record the |
| 235 // MessageLoop pointer before stopping the thread because Thread::Stop() will | 235 // MessageLoop pointer before stopping the thread because Thread::Stop() will |
| 236 // NULL out its own pointer. | 236 // NULL out its own pointer. |
| 237 MessageLoop* task_loop = task_thread_.message_loop(); | 237 MessageLoop* task_loop = task_thread_.message_loop(); |
| 238 task_thread_.Stop(); | 238 task_thread_.Stop(); |
| 239 | 239 |
| 240 EXPECT_EQ(task_loop, task_run_on); | 240 EXPECT_EQ(task_loop, task_run_on); |
|
dcheng
2017/02/07 07:28:44
And add some comments here to explain the new beha
tzik
2017/02/07 08:05:34
Acknowledged.
tzik
2017/02/07 08:33:26
Done.
| |
| 241 ASSERT_FALSE(task_deleted_on); | 241 EXPECT_EQ(task_loop, task_deleted_on); |
| 242 EXPECT_FALSE(reply_run_on); | 242 EXPECT_FALSE(reply_run_on); |
| 243 ASSERT_FALSE(reply_deleted_on); | 243 ASSERT_FALSE(reply_deleted_on); |
| 244 EXPECT_EQ(task_delete_order, reply_delete_order); | |
| 245 | 244 |
| 246 // The PostTaskAndReplyRelay is leaked here. Even if we had a reference to | 245 // The PostTaskAndReplyRelay is leaked here. Even if we had a reference to |
| 247 // it, we cannot just delete it because PostTaskAndReplyRelay's destructor | 246 // it, we cannot just delete it because PostTaskAndReplyRelay's destructor |
| 248 // checks that MessageLoop::current() is the the same as when the | 247 // checks that MessageLoop::current() is the the same as when the |
| 249 // PostTaskAndReplyRelay object was constructed. However, this loop must have | 248 // PostTaskAndReplyRelay object was constructed. However, this loop must have |
| 250 // already been deleted in order to perform this test. See | 249 // already been deleted in order to perform this test. See |
| 251 // http://crbug.com/86301. | 250 // http://crbug.com/86301. |
| 252 } | 251 } |
| 253 | 252 |
| 254 class MessageLoopTaskRunnerThreadingTest : public testing::Test { | 253 class MessageLoopTaskRunnerThreadingTest : public testing::Test { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 353 new Thread("MessageLoopTaskRunnerThreadingTest_Dummy")); | 352 new Thread("MessageLoopTaskRunnerThreadingTest_Dummy")); |
| 354 test_thread->Start(); | 353 test_thread->Start(); |
| 355 task_runner = test_thread->task_runner(); | 354 task_runner = test_thread->task_runner(); |
| 356 } | 355 } |
| 357 bool ret = task_runner->PostTask( | 356 bool ret = task_runner->PostTask( |
| 358 FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun)); | 357 FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun)); |
| 359 EXPECT_FALSE(ret); | 358 EXPECT_FALSE(ret); |
| 360 } | 359 } |
| 361 | 360 |
| 362 } // namespace base | 361 } // namespace base |
| OLD | NEW |