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 |