| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/cancelable_task_tracker.h" | 5 #include "base/task/cancelable_task_tracker.h" |
| 6 | 6 |
| 7 #include <cstddef> | 7 #include <cstddef> |
| 8 #include <deque> | 8 #include <deque> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
| 15 #include "base/memory/weak_ptr.h" | 15 #include "base/memory/weak_ptr.h" |
| 16 #include "base/message_loop/message_loop.h" | |
| 17 #include "base/run_loop.h" | 16 #include "base/run_loop.h" |
| 17 #include "base/single_thread_task_runner.h" |
| 18 #include "base/test/test_simple_task_runner.h" | 18 #include "base/test/test_simple_task_runner.h" |
| 19 #include "base/threading/thread.h" | 19 #include "base/threading/thread.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 21 | 21 |
| 22 namespace base { | 22 namespace base { |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 class CancelableTaskTrackerTest : public testing::Test { | 26 class CancelableTaskTrackerTest : public testing::Test { |
| 27 protected: | 27 protected: |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 | 77 |
| 78 } // namespace | 78 } // namespace |
| 79 | 79 |
| 80 // With the task tracker, post a task, a task with a reply, and get a | 80 // With the task tracker, post a task, a task with a reply, and get a |
| 81 // new task id without canceling any of them. The tasks and the reply | 81 // new task id without canceling any of them. The tasks and the reply |
| 82 // should run and the "is canceled" callback should return false. | 82 // should run and the "is canceled" callback should return false. |
| 83 TEST_F(CancelableTaskTrackerTest, NoCancel) { | 83 TEST_F(CancelableTaskTrackerTest, NoCancel) { |
| 84 Thread worker_thread("worker thread"); | 84 Thread worker_thread("worker thread"); |
| 85 ASSERT_TRUE(worker_thread.Start()); | 85 ASSERT_TRUE(worker_thread.Start()); |
| 86 | 86 |
| 87 ignore_result(task_tracker_.PostTask(worker_thread.message_loop_proxy().get(), | 87 ignore_result(task_tracker_.PostTask(worker_thread.task_runner().get(), |
| 88 FROM_HERE, | 88 FROM_HERE, |
| 89 MakeExpectedRunClosure(FROM_HERE))); | 89 MakeExpectedRunClosure(FROM_HERE))); |
| 90 | 90 |
| 91 ignore_result( | 91 ignore_result(task_tracker_.PostTaskAndReply( |
| 92 task_tracker_.PostTaskAndReply(worker_thread.message_loop_proxy().get(), | 92 worker_thread.task_runner().get(), FROM_HERE, |
| 93 FROM_HERE, | 93 MakeExpectedRunClosure(FROM_HERE), MakeExpectedRunClosure(FROM_HERE))); |
| 94 MakeExpectedRunClosure(FROM_HERE), | |
| 95 MakeExpectedRunClosure(FROM_HERE))); | |
| 96 | 94 |
| 97 CancelableTaskTracker::IsCanceledCallback is_canceled; | 95 CancelableTaskTracker::IsCanceledCallback is_canceled; |
| 98 ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled)); | 96 ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled)); |
| 99 | 97 |
| 100 worker_thread.Stop(); | 98 worker_thread.Stop(); |
| 101 | 99 |
| 102 RunCurrentLoopUntilIdle(); | 100 RunCurrentLoopUntilIdle(); |
| 103 | 101 |
| 104 EXPECT_FALSE(is_canceled.Run()); | 102 EXPECT_FALSE(is_canceled.Run()); |
| 105 } | 103 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 task_tracker_.TryCancel(task_id); | 157 task_tracker_.TryCancel(task_id); |
| 160 } | 158 } |
| 161 | 159 |
| 162 // Post a task with reply with the task tracker on a worker thread and | 160 // Post a task with reply with the task tracker on a worker thread and |
| 163 // cancel it before running the current message loop. The task should | 161 // cancel it before running the current message loop. The task should |
| 164 // run but the reply should not. | 162 // run but the reply should not. |
| 165 TEST_F(CancelableTaskTrackerTest, CancelReplyDifferentThread) { | 163 TEST_F(CancelableTaskTrackerTest, CancelReplyDifferentThread) { |
| 166 Thread worker_thread("worker thread"); | 164 Thread worker_thread("worker thread"); |
| 167 ASSERT_TRUE(worker_thread.Start()); | 165 ASSERT_TRUE(worker_thread.Start()); |
| 168 | 166 |
| 169 CancelableTaskTracker::TaskId task_id = | 167 CancelableTaskTracker::TaskId task_id = task_tracker_.PostTaskAndReply( |
| 170 task_tracker_.PostTaskAndReply(worker_thread.message_loop_proxy().get(), | 168 worker_thread.task_runner().get(), FROM_HERE, Bind(&DoNothing), |
| 171 FROM_HERE, | 169 MakeExpectedNotRunClosure(FROM_HERE)); |
| 172 Bind(&DoNothing), | |
| 173 MakeExpectedNotRunClosure(FROM_HERE)); | |
| 174 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id); | 170 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id); |
| 175 | 171 |
| 176 task_tracker_.TryCancel(task_id); | 172 task_tracker_.TryCancel(task_id); |
| 177 | 173 |
| 178 worker_thread.Stop(); | 174 worker_thread.Stop(); |
| 179 } | 175 } |
| 180 | 176 |
| 181 void ExpectIsCanceled( | 177 void ExpectIsCanceled( |
| 182 const CancelableTaskTracker::IsCanceledCallback& is_canceled, | 178 const CancelableTaskTracker::IsCanceledCallback& is_canceled, |
| 183 bool expected_is_canceled) { | 179 bool expected_is_canceled) { |
| 184 EXPECT_EQ(expected_is_canceled, is_canceled.Run()); | 180 EXPECT_EQ(expected_is_canceled, is_canceled.Run()); |
| 185 } | 181 } |
| 186 | 182 |
| 187 // Create a new task ID and check its status on a separate thread | 183 // Create a new task ID and check its status on a separate thread |
| 188 // before and after canceling. The is-canceled callback should be | 184 // before and after canceling. The is-canceled callback should be |
| 189 // thread-safe (i.e., nothing should blow up). | 185 // thread-safe (i.e., nothing should blow up). |
| 190 TEST_F(CancelableTaskTrackerTest, NewTrackedTaskIdDifferentThread) { | 186 TEST_F(CancelableTaskTrackerTest, NewTrackedTaskIdDifferentThread) { |
| 191 CancelableTaskTracker::IsCanceledCallback is_canceled; | 187 CancelableTaskTracker::IsCanceledCallback is_canceled; |
| 192 CancelableTaskTracker::TaskId task_id = | 188 CancelableTaskTracker::TaskId task_id = |
| 193 task_tracker_.NewTrackedTaskId(&is_canceled); | 189 task_tracker_.NewTrackedTaskId(&is_canceled); |
| 194 | 190 |
| 195 EXPECT_FALSE(is_canceled.Run()); | 191 EXPECT_FALSE(is_canceled.Run()); |
| 196 | 192 |
| 197 Thread other_thread("other thread"); | 193 Thread other_thread("other thread"); |
| 198 ASSERT_TRUE(other_thread.Start()); | 194 ASSERT_TRUE(other_thread.Start()); |
| 199 other_thread.message_loop_proxy()->PostTask( | 195 other_thread.task_runner()->PostTask( |
| 200 FROM_HERE, Bind(&ExpectIsCanceled, is_canceled, false)); | 196 FROM_HERE, Bind(&ExpectIsCanceled, is_canceled, false)); |
| 201 other_thread.Stop(); | 197 other_thread.Stop(); |
| 202 | 198 |
| 203 task_tracker_.TryCancel(task_id); | 199 task_tracker_.TryCancel(task_id); |
| 204 | 200 |
| 205 ASSERT_TRUE(other_thread.Start()); | 201 ASSERT_TRUE(other_thread.Start()); |
| 206 other_thread.message_loop_proxy()->PostTask( | 202 other_thread.task_runner()->PostTask( |
| 207 FROM_HERE, Bind(&ExpectIsCanceled, is_canceled, true)); | 203 FROM_HERE, Bind(&ExpectIsCanceled, is_canceled, true)); |
| 208 other_thread.Stop(); | 204 other_thread.Stop(); |
| 209 } | 205 } |
| 210 | 206 |
| 211 // With the task tracker, post a task, a task with a reply, get a new | 207 // With the task tracker, post a task, a task with a reply, get a new |
| 212 // task id, and then cancel all of them. None of the tasks nor the | 208 // task id, and then cancel all of them. None of the tasks nor the |
| 213 // reply should run and the "is canceled" callback should return | 209 // reply should run and the "is canceled" callback should return |
| 214 // true. | 210 // true. |
| 215 TEST_F(CancelableTaskTrackerTest, CancelAll) { | 211 TEST_F(CancelableTaskTrackerTest, CancelAll) { |
| 216 scoped_refptr<TestSimpleTaskRunner> test_task_runner( | 212 scoped_refptr<TestSimpleTaskRunner> test_task_runner( |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 ignore_result(task_tracker->PostTask( | 367 ignore_result(task_tracker->PostTask( |
| 372 scoped_refptr<TestSimpleTaskRunner>(new TestSimpleTaskRunner()).get(), | 368 scoped_refptr<TestSimpleTaskRunner>(new TestSimpleTaskRunner()).get(), |
| 373 FROM_HERE, | 369 FROM_HERE, |
| 374 Bind(&DoNothing))); | 370 Bind(&DoNothing))); |
| 375 } | 371 } |
| 376 | 372 |
| 377 TEST_F(CancelableTaskTrackerDeathTest, PostFromDifferentThread) { | 373 TEST_F(CancelableTaskTrackerDeathTest, PostFromDifferentThread) { |
| 378 Thread bad_thread("bad thread"); | 374 Thread bad_thread("bad thread"); |
| 379 ASSERT_TRUE(bad_thread.Start()); | 375 ASSERT_TRUE(bad_thread.Start()); |
| 380 | 376 |
| 381 bad_thread.message_loop_proxy()->PostTask( | 377 bad_thread.task_runner()->PostTask( |
| 382 FROM_HERE, | 378 FROM_HERE, Bind(&MaybeRunDeadlyTaskTrackerMemberFunction, |
| 383 Bind(&MaybeRunDeadlyTaskTrackerMemberFunction, | 379 Unretained(&task_tracker_), Bind(&PostDoNothingTask))); |
| 384 Unretained(&task_tracker_), | |
| 385 Bind(&PostDoNothingTask))); | |
| 386 } | 380 } |
| 387 | 381 |
| 388 void TryCancel(CancelableTaskTracker::TaskId task_id, | 382 void TryCancel(CancelableTaskTracker::TaskId task_id, |
| 389 CancelableTaskTracker* task_tracker) { | 383 CancelableTaskTracker* task_tracker) { |
| 390 task_tracker->TryCancel(task_id); | 384 task_tracker->TryCancel(task_id); |
| 391 } | 385 } |
| 392 | 386 |
| 393 TEST_F(CancelableTaskTrackerDeathTest, CancelOnDifferentThread) { | 387 TEST_F(CancelableTaskTrackerDeathTest, CancelOnDifferentThread) { |
| 394 scoped_refptr<TestSimpleTaskRunner> test_task_runner( | 388 scoped_refptr<TestSimpleTaskRunner> test_task_runner( |
| 395 new TestSimpleTaskRunner()); | 389 new TestSimpleTaskRunner()); |
| 396 | 390 |
| 397 Thread bad_thread("bad thread"); | 391 Thread bad_thread("bad thread"); |
| 398 ASSERT_TRUE(bad_thread.Start()); | 392 ASSERT_TRUE(bad_thread.Start()); |
| 399 | 393 |
| 400 CancelableTaskTracker::TaskId task_id = task_tracker_.PostTask( | 394 CancelableTaskTracker::TaskId task_id = task_tracker_.PostTask( |
| 401 test_task_runner.get(), FROM_HERE, Bind(&DoNothing)); | 395 test_task_runner.get(), FROM_HERE, Bind(&DoNothing)); |
| 402 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id); | 396 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id); |
| 403 | 397 |
| 404 bad_thread.message_loop_proxy()->PostTask( | 398 bad_thread.task_runner()->PostTask( |
| 405 FROM_HERE, | 399 FROM_HERE, Bind(&MaybeRunDeadlyTaskTrackerMemberFunction, |
| 406 Bind(&MaybeRunDeadlyTaskTrackerMemberFunction, | 400 Unretained(&task_tracker_), Bind(&TryCancel, task_id))); |
| 407 Unretained(&task_tracker_), | |
| 408 Bind(&TryCancel, task_id))); | |
| 409 | 401 |
| 410 test_task_runner->RunUntilIdle(); | 402 test_task_runner->RunUntilIdle(); |
| 411 } | 403 } |
| 412 | 404 |
| 413 TEST_F(CancelableTaskTrackerDeathTest, CancelAllOnDifferentThread) { | 405 TEST_F(CancelableTaskTrackerDeathTest, CancelAllOnDifferentThread) { |
| 414 scoped_refptr<TestSimpleTaskRunner> test_task_runner( | 406 scoped_refptr<TestSimpleTaskRunner> test_task_runner( |
| 415 new TestSimpleTaskRunner()); | 407 new TestSimpleTaskRunner()); |
| 416 | 408 |
| 417 Thread bad_thread("bad thread"); | 409 Thread bad_thread("bad thread"); |
| 418 ASSERT_TRUE(bad_thread.Start()); | 410 ASSERT_TRUE(bad_thread.Start()); |
| 419 | 411 |
| 420 CancelableTaskTracker::TaskId task_id = task_tracker_.PostTask( | 412 CancelableTaskTracker::TaskId task_id = task_tracker_.PostTask( |
| 421 test_task_runner.get(), FROM_HERE, Bind(&DoNothing)); | 413 test_task_runner.get(), FROM_HERE, Bind(&DoNothing)); |
| 422 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id); | 414 EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id); |
| 423 | 415 |
| 424 bad_thread.message_loop_proxy()->PostTask( | 416 bad_thread.task_runner()->PostTask( |
| 425 FROM_HERE, | 417 FROM_HERE, |
| 426 Bind(&MaybeRunDeadlyTaskTrackerMemberFunction, | 418 Bind(&MaybeRunDeadlyTaskTrackerMemberFunction, Unretained(&task_tracker_), |
| 427 Unretained(&task_tracker_), | |
| 428 Bind(&CancelableTaskTracker::TryCancelAll))); | 419 Bind(&CancelableTaskTracker::TryCancelAll))); |
| 429 | 420 |
| 430 test_task_runner->RunUntilIdle(); | 421 test_task_runner->RunUntilIdle(); |
| 431 } | 422 } |
| 432 | 423 |
| 433 } // namespace base | 424 } // namespace base |
| OLD | NEW |