Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/task.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 5 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
| 6 #include "base/task.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/threading/thread.h" | |
| 7 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 8 | 12 |
| 9 namespace { | 13 namespace { |
| 10 | 14 |
| 11 class CancelInDestructor : public base::RefCounted<CancelInDestructor> { | 15 class CancelInDestructor : public base::RefCounted<CancelInDestructor> { |
| 12 public: | 16 public: |
| 13 CancelInDestructor() : cancelable_task_(NULL) {} | 17 CancelInDestructor() : cancelable_task_(NULL) {} |
| 14 | 18 |
| 15 void Start() { | 19 void Start() { |
| 16 if (cancelable_task_) { | 20 if (cancelable_task_) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 EXPECT_EQ(0, run_count); | 104 EXPECT_EQ(0, run_count); |
| 101 done_task->Run(); | 105 done_task->Run(); |
| 102 EXPECT_FALSE(was_deleted); | 106 EXPECT_FALSE(was_deleted); |
| 103 EXPECT_EQ(1, run_count); | 107 EXPECT_EQ(1, run_count); |
| 104 } | 108 } |
| 105 EXPECT_EQ(1, run_count); | 109 EXPECT_EQ(1, run_count); |
| 106 delete done_task; | 110 delete done_task; |
| 107 EXPECT_TRUE(was_deleted); | 111 EXPECT_TRUE(was_deleted); |
| 108 } | 112 } |
| 109 | 113 |
| 114 class LoopRecorder : public base::RefCountedThreadSafe<LoopRecorder> { | |
|
willchan no longer on Chromium
2011/08/17 04:36:07
I'm not sure why you make this RefCountedThreadSaf
awong
2011/08/17 05:16:00
I figured that in the case that someone introduced
| |
| 115 public: | |
| 116 LoopRecorder(MessageLoop** run_on, MessageLoop** deleted_on) | |
| 117 : run_on_(run_on), | |
| 118 deleted_on_(deleted_on) { | |
| 119 } | |
| 120 | |
| 121 void RecordRun() { | |
| 122 *run_on_ = MessageLoop::current(); | |
| 123 } | |
| 124 | |
| 125 private: | |
| 126 friend class base::RefCountedThreadSafe<LoopRecorder>; | |
| 127 ~LoopRecorder() { | |
| 128 *deleted_on_ = MessageLoop::current(); | |
| 129 } | |
| 130 | |
| 131 MessageLoop** run_on_; | |
| 132 MessageLoop** deleted_on_; | |
| 133 }; | |
| 134 | |
| 135 void RecordLoop(scoped_refptr<LoopRecorder> recorder) { | |
| 136 recorder->RecordRun(); | |
| 137 } | |
| 138 | |
| 139 void RecordLoopAndQuit(scoped_refptr<LoopRecorder> recorder) { | |
| 140 recorder->RecordRun(); | |
| 141 MessageLoop::current()->Quit(); | |
| 142 } | |
| 143 | |
| 144 TEST(TaskTest, TestPostTaskAndReplyRelay_Basic) { | |
| 145 using base::internal::PostTaskAndReplyRelay; | |
| 146 | |
| 147 MessageLoop current_loop; | |
| 148 | |
| 149 MessageLoop* task_run_on = NULL; | |
| 150 MessageLoop* task_deleted_on = NULL; | |
| 151 MessageLoop* reply_run_on = NULL; | |
| 152 MessageLoop* reply_deleted_on = NULL; | |
| 153 | |
| 154 scoped_refptr<LoopRecorder> task_recoder = | |
|
willchan no longer on Chromium
2011/08/17 04:36:07
s/task_recoder/task_recorder/?
awong
2011/08/17 05:16:00
Will fix tomorrow.
| |
| 155 new LoopRecorder(&task_run_on, &task_deleted_on); | |
| 156 scoped_refptr<LoopRecorder> reply_recoder = | |
| 157 new LoopRecorder(&reply_run_on, &reply_deleted_on); | |
| 158 | |
| 159 PostTaskAndReplyRelay* relay = | |
| 160 new PostTaskAndReplyRelay( | |
| 161 FROM_HERE, | |
| 162 base::Bind(&RecordLoop, task_recoder), | |
| 163 base::Bind(&RecordLoopAndQuit, reply_recoder)); | |
| 164 | |
| 165 // Die if base::Bind doesn't retain a reference to the recorders. | |
| 166 task_recoder = NULL; | |
| 167 reply_recoder = NULL; | |
| 168 ASSERT_FALSE(task_deleted_on); | |
| 169 ASSERT_FALSE(reply_deleted_on); | |
| 170 | |
| 171 // Run the relay. | |
| 172 base::Thread task_thread("task_thread"); | |
| 173 task_thread.Start(); | |
| 174 task_thread.message_loop()->PostTask( | |
| 175 FROM_HERE, | |
| 176 base::Bind(&PostTaskAndReplyRelay::Run, base::Unretained(relay))); | |
| 177 | |
| 178 current_loop.Run(); | |
| 179 | |
| 180 EXPECT_EQ(task_thread.message_loop(), task_run_on); | |
| 181 EXPECT_EQ(¤t_loop, task_deleted_on); | |
| 182 EXPECT_EQ(¤t_loop, reply_run_on); | |
| 183 EXPECT_EQ(¤t_loop, reply_deleted_on); | |
| 184 } | |
| 185 | |
| 186 TEST(TaskTest, TestPostTaskAndReplyRelay_SameLoop) { | |
| 187 using base::internal::PostTaskAndReplyRelay; | |
| 188 | |
| 189 MessageLoop current_loop; | |
| 190 | |
| 191 MessageLoop* task_run_on = NULL; | |
| 192 MessageLoop* task_deleted_on = NULL; | |
| 193 MessageLoop* reply_run_on = NULL; | |
| 194 MessageLoop* reply_deleted_on = NULL; | |
| 195 | |
| 196 scoped_refptr<LoopRecorder> task_recoder = | |
| 197 new LoopRecorder(&task_run_on, &task_deleted_on); | |
| 198 scoped_refptr<LoopRecorder> reply_recoder = | |
| 199 new LoopRecorder(&reply_run_on, &reply_deleted_on); | |
| 200 | |
| 201 PostTaskAndReplyRelay* relay = | |
| 202 new PostTaskAndReplyRelay( | |
| 203 FROM_HERE, | |
| 204 base::Bind(&RecordLoop, task_recoder), | |
| 205 base::Bind(&RecordLoopAndQuit, reply_recoder)); | |
| 206 | |
| 207 // Die if base::Bind doesn't retain a reference to the recorders. | |
| 208 task_recoder = NULL; | |
| 209 reply_recoder = NULL; | |
| 210 ASSERT_FALSE(task_deleted_on); | |
| 211 ASSERT_FALSE(reply_deleted_on); | |
| 212 | |
| 213 // Run the relay. | |
| 214 current_loop.PostTask( | |
| 215 FROM_HERE, | |
| 216 base::Bind(&PostTaskAndReplyRelay::Run, base::Unretained(relay))); | |
| 217 | |
| 218 current_loop.Run(); | |
| 219 | |
| 220 EXPECT_EQ(¤t_loop, task_run_on); | |
| 221 EXPECT_EQ(¤t_loop, task_deleted_on); | |
| 222 EXPECT_EQ(¤t_loop, reply_run_on); | |
| 223 EXPECT_EQ(¤t_loop, reply_deleted_on); | |
| 224 } | |
| 225 | |
| 226 TEST(TaskTest, TestPostTaskAndReplyRelay_DeadReplyLoopDoesNotDelete) { | |
| 227 using base::internal::PostTaskAndReplyRelay; | |
| 228 | |
| 229 scoped_ptr<MessageLoop> current_loop(new MessageLoop()); | |
| 230 | |
| 231 MessageLoop* task_run_on = NULL; | |
| 232 MessageLoop* task_deleted_on = NULL; | |
| 233 MessageLoop* reply_run_on = NULL; | |
| 234 MessageLoop* reply_deleted_on = NULL; | |
| 235 | |
| 236 scoped_refptr<LoopRecorder> task_recoder = | |
| 237 new LoopRecorder(&task_run_on, &task_deleted_on); | |
| 238 scoped_refptr<LoopRecorder> reply_recoder = | |
| 239 new LoopRecorder(&reply_run_on, &reply_deleted_on); | |
| 240 | |
| 241 PostTaskAndReplyRelay* relay = | |
| 242 new PostTaskAndReplyRelay( | |
| 243 FROM_HERE, | |
| 244 base::Bind(&RecordLoop, task_recoder), | |
| 245 base::Bind(&RecordLoopAndQuit, reply_recoder)); | |
| 246 | |
| 247 // Die if base::Bind doesn't retain a reference to the recorders. | |
| 248 task_recoder = NULL; | |
| 249 reply_recoder = NULL; | |
| 250 ASSERT_FALSE(task_deleted_on); | |
| 251 ASSERT_FALSE(reply_deleted_on); | |
| 252 | |
| 253 // Run the relay. | |
| 254 base::Thread task_thread("task_thread"); | |
| 255 task_thread.Start(); | |
| 256 task_thread.message_loop()->PostTask( | |
| 257 FROM_HERE, | |
| 258 base::Bind(&PostTaskAndReplyRelay::Run, base::Unretained(relay))); | |
| 259 | |
| 260 // Mercilessly whack the current loop before |reply| gets to run. | |
| 261 current_loop.reset(); | |
| 262 | |
| 263 // This should ensure the relay has been run. We need to record the | |
| 264 // MessageLoop pointer before stopping the thread because Thread::Stop() will | |
| 265 // NULL out its own pointer. | |
| 266 MessageLoop* task_loop = task_thread.message_loop(); | |
| 267 task_thread.Stop(); | |
| 268 | |
| 269 EXPECT_EQ(task_loop, task_run_on); | |
| 270 ASSERT_FALSE(task_deleted_on); | |
| 271 EXPECT_FALSE(reply_run_on); | |
| 272 ASSERT_FALSE(reply_deleted_on); | |
| 273 | |
| 274 // Relay is leaked here. | |
| 275 // TODO(ajwong): Is there a way to make Valgrind not hate us? | |
|
willchan no longer on Chromium
2011/08/17 04:36:07
delete relay; :)
awong
2011/08/17 05:16:00
Tried that. Dies cause the Relay asserts that it i
| |
| 276 } | |
| 277 | |
| 110 } // namespace | 278 } // namespace |
| OLD | NEW |