| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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_scheduler/scheduler_worker.h" | 5 #include "base/task_scheduler/scheduler_worker.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 16 #include "base/message_loop/message_loop.h" |
| 16 #include "base/synchronization/condition_variable.h" | 17 #include "base/synchronization/condition_variable.h" |
| 17 #include "base/synchronization/waitable_event.h" | 18 #include "base/synchronization/waitable_event.h" |
| 18 #include "base/task_scheduler/scheduler_lock.h" | 19 #include "base/task_scheduler/scheduler_lock.h" |
| 19 #include "base/task_scheduler/sequence.h" | 20 #include "base/task_scheduler/sequence.h" |
| 20 #include "base/task_scheduler/task.h" | 21 #include "base/task_scheduler/task.h" |
| 21 #include "base/task_scheduler/task_tracker.h" | 22 #include "base/task_scheduler/task_tracker.h" |
| 22 #include "base/threading/platform_thread.h" | 23 #include "base/threading/platform_thread.h" |
| 23 #include "base/time/time.h" | 24 #include "base/time/time.h" |
| 24 #include "build/build_config.h" | 25 #include "build/build_config.h" |
| 25 #include "testing/gmock/include/gmock/gmock.h" | 26 #include "testing/gmock/include/gmock/gmock.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 54 ADD_FAILURE() << "Unexpected call to ReEnqueueSequence()"; | 55 ADD_FAILURE() << "Unexpected call to ReEnqueueSequence()"; |
| 55 } | 56 } |
| 56 TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } | 57 TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } |
| 57 bool CanDetach(SchedulerWorker* worker) override { return false; } | 58 bool CanDetach(SchedulerWorker* worker) override { return false; } |
| 58 | 59 |
| 59 private: | 60 private: |
| 60 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDefaultDelegate); | 61 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDefaultDelegate); |
| 61 }; | 62 }; |
| 62 | 63 |
| 63 // The test parameter is the number of Tasks per Sequence returned by GetWork(). | 64 // The test parameter is the number of Tasks per Sequence returned by GetWork(). |
| 64 class TaskSchedulerWorkerTest : public testing::TestWithParam<size_t> { | 65 class TaskSchedulerWorkerDoWorkTest : public testing::TestWithParam<size_t> { |
| 65 protected: | 66 protected: |
| 66 TaskSchedulerWorkerTest() | 67 TaskSchedulerWorkerDoWorkTest() |
| 67 : main_entry_called_(WaitableEvent::ResetPolicy::MANUAL, | 68 : |
| 69 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) |
| 70 task_tracker_(&watch_file_descriptor_message_loop_), |
| 71 #endif |
| 72 main_entry_called_(WaitableEvent::ResetPolicy::MANUAL, |
| 68 WaitableEvent::InitialState::NOT_SIGNALED), | 73 WaitableEvent::InitialState::NOT_SIGNALED), |
| 69 num_get_work_cv_(lock_.CreateConditionVariable()), | 74 num_get_work_cv_(lock_.CreateConditionVariable()), |
| 70 worker_set_(WaitableEvent::ResetPolicy::MANUAL, | 75 worker_set_(WaitableEvent::ResetPolicy::MANUAL, |
| 71 WaitableEvent::InitialState::NOT_SIGNALED) {} | 76 WaitableEvent::InitialState::NOT_SIGNALED) { |
| 77 } |
| 72 | 78 |
| 73 void SetUp() override { | 79 void SetUp() override { |
| 74 worker_ = SchedulerWorker::Create( | 80 worker_ = SchedulerWorker::Create( |
| 75 ThreadPriority::NORMAL, MakeUnique<TestSchedulerWorkerDelegate>(this), | 81 ThreadPriority::NORMAL, MakeUnique<TestSchedulerWorkerDelegate>(this), |
| 76 &task_tracker_, SchedulerWorker::InitialState::ALIVE); | 82 &task_tracker_, SchedulerWorker::InitialState::ALIVE); |
| 77 ASSERT_TRUE(worker_); | 83 ASSERT_TRUE(worker_); |
| 78 worker_set_.Signal(); | 84 worker_set_.Signal(); |
| 79 main_entry_called_.Wait(); | 85 main_entry_called_.Wait(); |
| 80 } | 86 } |
| 81 | 87 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 std::vector<scoped_refptr<Sequence>> EnqueuedSequences() { | 122 std::vector<scoped_refptr<Sequence>> EnqueuedSequences() { |
| 117 AutoSchedulerLock auto_lock(lock_); | 123 AutoSchedulerLock auto_lock(lock_); |
| 118 return re_enqueued_sequences_; | 124 return re_enqueued_sequences_; |
| 119 } | 125 } |
| 120 | 126 |
| 121 std::unique_ptr<SchedulerWorker> worker_; | 127 std::unique_ptr<SchedulerWorker> worker_; |
| 122 | 128 |
| 123 private: | 129 private: |
| 124 class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate { | 130 class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate { |
| 125 public: | 131 public: |
| 126 TestSchedulerWorkerDelegate(TaskSchedulerWorkerTest* outer) | 132 TestSchedulerWorkerDelegate(TaskSchedulerWorkerDoWorkTest* outer) |
| 127 : outer_(outer) {} | 133 : outer_(outer) {} |
| 128 | 134 |
| 129 ~TestSchedulerWorkerDelegate() override { | 135 ~TestSchedulerWorkerDelegate() override { |
| 130 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected()); | 136 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected()); |
| 131 } | 137 } |
| 132 | 138 |
| 133 // SchedulerWorker::Delegate: | 139 // SchedulerWorker::Delegate: |
| 134 void OnMainEntry(SchedulerWorker* worker, | 140 void OnMainEntry(SchedulerWorker* worker, |
| 135 const TimeDelta& detach_duration) override { | 141 const TimeDelta& detach_duration) override { |
| 136 outer_->worker_set_.Wait(); | 142 outer_->worker_set_.Wait(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 161 // Check if a Sequence should be returned. | 167 // Check if a Sequence should be returned. |
| 162 if (outer_->num_sequences_to_create_ == 0) | 168 if (outer_->num_sequences_to_create_ == 0) |
| 163 return nullptr; | 169 return nullptr; |
| 164 --outer_->num_sequences_to_create_; | 170 --outer_->num_sequences_to_create_; |
| 165 } | 171 } |
| 166 | 172 |
| 167 // Create a Sequence with TasksPerSequence() Tasks. | 173 // Create a Sequence with TasksPerSequence() Tasks. |
| 168 scoped_refptr<Sequence> sequence(new Sequence); | 174 scoped_refptr<Sequence> sequence(new Sequence); |
| 169 for (size_t i = 0; i < outer_->TasksPerSequence(); ++i) { | 175 for (size_t i = 0; i < outer_->TasksPerSequence(); ++i) { |
| 170 std::unique_ptr<Task> task(new Task( | 176 std::unique_ptr<Task> task(new Task( |
| 171 FROM_HERE, Bind(&TaskSchedulerWorkerTest::RunTaskCallback, | 177 FROM_HERE, Bind(&TaskSchedulerWorkerDoWorkTest::RunTaskCallback, |
| 172 Unretained(outer_)), | 178 Unretained(outer_)), |
| 173 TaskTraits(), TimeDelta())); | 179 TaskTraits(), TimeDelta())); |
| 174 EXPECT_TRUE(outer_->task_tracker_.WillPostTask(task.get())); | 180 EXPECT_TRUE(outer_->task_tracker_.WillPostTask(task.get())); |
| 175 sequence->PushTask(std::move(task)); | 181 sequence->PushTask(std::move(task)); |
| 176 } | 182 } |
| 177 | 183 |
| 178 ExpectCallToDidRunTaskWithPriority(sequence->PeekTaskTraits().priority()); | 184 ExpectCallToDidRunTaskWithPriority(sequence->PeekTaskTraits().priority()); |
| 179 | 185 |
| 180 { | 186 { |
| 181 // Add the Sequence to the vector of created Sequences. | 187 // Add the Sequence to the vector of created Sequences. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 AutoSchedulerLock auto_lock(expect_did_run_task_with_priority_lock_); | 229 AutoSchedulerLock auto_lock(expect_did_run_task_with_priority_lock_); |
| 224 expect_did_run_task_with_priority_ = true; | 230 expect_did_run_task_with_priority_ = true; |
| 225 expected_task_priority_ = task_priority; | 231 expected_task_priority_ = task_priority; |
| 226 } | 232 } |
| 227 | 233 |
| 228 bool IsCallToDidRunTaskWithPriorityExpected() const { | 234 bool IsCallToDidRunTaskWithPriorityExpected() const { |
| 229 AutoSchedulerLock auto_lock(expect_did_run_task_with_priority_lock_); | 235 AutoSchedulerLock auto_lock(expect_did_run_task_with_priority_lock_); |
| 230 return expect_did_run_task_with_priority_; | 236 return expect_did_run_task_with_priority_; |
| 231 } | 237 } |
| 232 | 238 |
| 233 TaskSchedulerWorkerTest* outer_; | 239 TaskSchedulerWorkerDoWorkTest* const outer_; |
| 234 | 240 |
| 235 // Synchronizes access to |expect_did_run_task_with_priority_| and | 241 // Synchronizes access to |expect_did_run_task_with_priority_| and |
| 236 // |expected_task_priority_|. | 242 // |expected_task_priority_|. |
| 237 mutable SchedulerLock expect_did_run_task_with_priority_lock_; | 243 mutable SchedulerLock expect_did_run_task_with_priority_lock_; |
| 238 | 244 |
| 239 // Whether the next method called on this delegate should be | 245 // Whether the next method called on this delegate should be |
| 240 // DidRunTaskWithPriority(). | 246 // DidRunTaskWithPriority(). |
| 241 bool expect_did_run_task_with_priority_ = false; | 247 bool expect_did_run_task_with_priority_ = false; |
| 242 | 248 |
| 243 // Expected priority for the next call to DidRunTaskWithPriority(). | 249 // Expected priority for the next call to DidRunTaskWithPriority(). |
| 244 TaskPriority expected_task_priority_ = TaskPriority::BACKGROUND; | 250 TaskPriority expected_task_priority_ = TaskPriority::BACKGROUND; |
| 245 }; | 251 }; |
| 246 | 252 |
| 247 void RunTaskCallback() { | 253 void RunTaskCallback() { |
| 248 AutoSchedulerLock auto_lock(lock_); | 254 AutoSchedulerLock auto_lock(lock_); |
| 249 ++num_run_tasks_; | 255 ++num_run_tasks_; |
| 250 EXPECT_LE(num_run_tasks_, created_sequences_.size()); | 256 EXPECT_LE(num_run_tasks_, created_sequences_.size()); |
| 251 } | 257 } |
| 252 | 258 |
| 259 private: |
| 260 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) |
| 261 MessageLoopForIO watch_file_descriptor_message_loop_; |
| 262 #endif |
| 263 |
| 264 protected: |
| 253 TaskTracker task_tracker_; | 265 TaskTracker task_tracker_; |
| 254 | 266 |
| 255 // Synchronizes access to all members below. | 267 // Synchronizes access to all members below. |
| 256 mutable SchedulerLock lock_; | 268 mutable SchedulerLock lock_; |
| 257 | 269 |
| 258 // Signaled once OnMainEntry() has been called. | 270 // Signaled once OnMainEntry() has been called. |
| 259 WaitableEvent main_entry_called_; | 271 WaitableEvent main_entry_called_; |
| 260 | 272 |
| 261 // Number of Sequences that should be created by GetWork(). When this | 273 // Number of Sequences that should be created by GetWork(). When this |
| 262 // is 0, GetWork() returns nullptr. | 274 // is 0, GetWork() returns nullptr. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 276 | 288 |
| 277 // Sequences passed to EnqueueSequence(). | 289 // Sequences passed to EnqueueSequence(). |
| 278 std::vector<scoped_refptr<Sequence>> re_enqueued_sequences_; | 290 std::vector<scoped_refptr<Sequence>> re_enqueued_sequences_; |
| 279 | 291 |
| 280 // Number of times that RunTaskCallback() has been called. | 292 // Number of times that RunTaskCallback() has been called. |
| 281 size_t num_run_tasks_ = 0; | 293 size_t num_run_tasks_ = 0; |
| 282 | 294 |
| 283 // Signaled after |worker_| is set. | 295 // Signaled after |worker_| is set. |
| 284 WaitableEvent worker_set_; | 296 WaitableEvent worker_set_; |
| 285 | 297 |
| 286 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerTest); | 298 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerDoWorkTest); |
| 287 }; | 299 }; |
| 288 | 300 |
| 289 // Verify that when GetWork() continuously returns Sequences, all Tasks in these | 301 // Verify that when GetWork() continuously returns Sequences, all Tasks in these |
| 290 // Sequences run successfully. The test wakes up the SchedulerWorker once. | 302 // Sequences run successfully. The test wakes up the SchedulerWorker once. |
| 291 TEST_P(TaskSchedulerWorkerTest, ContinuousWork) { | 303 TEST_P(TaskSchedulerWorkerDoWorkTest, ContinuousWork) { |
| 292 // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to | 304 // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to |
| 293 // return nullptr. | 305 // return nullptr. |
| 294 SetNumSequencesToCreate(kNumSequencesPerTest); | 306 SetNumSequencesToCreate(kNumSequencesPerTest); |
| 295 | 307 |
| 296 // Expect |kNumSequencesPerTest| calls to GetWork() in which it returns a | 308 // Expect |kNumSequencesPerTest| calls to GetWork() in which it returns a |
| 297 // Sequence and one call in which its returns nullptr. | 309 // Sequence and one call in which its returns nullptr. |
| 298 const size_t kExpectedNumGetWork = kNumSequencesPerTest + 1; | 310 const size_t kExpectedNumGetWork = kNumSequencesPerTest + 1; |
| 299 SetMaxGetWork(kExpectedNumGetWork); | 311 SetMaxGetWork(kExpectedNumGetWork); |
| 300 | 312 |
| 301 // Wake up |worker_| and wait until GetWork() has been invoked the | 313 // Wake up |worker_| and wait until GetWork() has been invoked the |
| 302 // expected amount of times. | 314 // expected amount of times. |
| 303 worker_->WakeUp(); | 315 worker_->WakeUp(); |
| 304 WaitForNumGetWork(kExpectedNumGetWork); | 316 WaitForNumGetWork(kExpectedNumGetWork); |
| 305 | 317 |
| 306 // All tasks should have run. | 318 // All tasks should have run. |
| 307 EXPECT_EQ(kNumSequencesPerTest, NumRunTasks()); | 319 EXPECT_EQ(kNumSequencesPerTest, NumRunTasks()); |
| 308 | 320 |
| 309 // If Sequences returned by GetWork() contain more than one Task, they aren't | 321 // If Sequences returned by GetWork() contain more than one Task, they aren't |
| 310 // empty after the worker pops Tasks from them and thus should be returned to | 322 // empty after the worker pops Tasks from them and thus should be returned to |
| 311 // EnqueueSequence(). | 323 // EnqueueSequence(). |
| 312 if (TasksPerSequence() > 1) | 324 if (TasksPerSequence() > 1) |
| 313 EXPECT_EQ(CreatedSequences(), EnqueuedSequences()); | 325 EXPECT_EQ(CreatedSequences(), EnqueuedSequences()); |
| 314 else | 326 else |
| 315 EXPECT_TRUE(EnqueuedSequences().empty()); | 327 EXPECT_TRUE(EnqueuedSequences().empty()); |
| 316 } | 328 } |
| 317 | 329 |
| 318 // Verify that when GetWork() alternates between returning a Sequence and | 330 // Verify that when GetWork() alternates between returning a Sequence and |
| 319 // returning nullptr, all Tasks in the returned Sequences run successfully. The | 331 // returning nullptr, all Tasks in the returned Sequences run successfully. The |
| 320 // test wakes up the SchedulerWorker once for each Sequence. | 332 // test wakes up the SchedulerWorker once for each Sequence. |
| 321 TEST_P(TaskSchedulerWorkerTest, IntermittentWork) { | 333 TEST_P(TaskSchedulerWorkerDoWorkTest, IntermittentWork) { |
| 322 for (size_t i = 0; i < kNumSequencesPerTest; ++i) { | 334 for (size_t i = 0; i < kNumSequencesPerTest; ++i) { |
| 323 // Set GetWork() to return 1 Sequence before starting to return | 335 // Set GetWork() to return 1 Sequence before starting to return |
| 324 // nullptr. | 336 // nullptr. |
| 325 SetNumSequencesToCreate(1); | 337 SetNumSequencesToCreate(1); |
| 326 | 338 |
| 327 // Expect |i + 1| calls to GetWork() in which it returns a Sequence and | 339 // Expect |i + 1| calls to GetWork() in which it returns a Sequence and |
| 328 // |i + 1| calls in which it returns nullptr. | 340 // |i + 1| calls in which it returns nullptr. |
| 329 const size_t expected_num_get_work = 2 * (i + 1); | 341 const size_t expected_num_get_work = 2 * (i + 1); |
| 330 SetMaxGetWork(expected_num_get_work); | 342 SetMaxGetWork(expected_num_get_work); |
| 331 | 343 |
| 332 // Wake up |worker_| and wait until GetWork() has been invoked | 344 // Wake up |worker_| and wait until GetWork() has been invoked |
| 333 // the expected amount of times. | 345 // the expected amount of times. |
| 334 worker_->WakeUp(); | 346 worker_->WakeUp(); |
| 335 WaitForNumGetWork(expected_num_get_work); | 347 WaitForNumGetWork(expected_num_get_work); |
| 336 | 348 |
| 337 // The Task should have run | 349 // The Task should have run |
| 338 EXPECT_EQ(i + 1, NumRunTasks()); | 350 EXPECT_EQ(i + 1, NumRunTasks()); |
| 339 | 351 |
| 340 // If Sequences returned by GetWork() contain more than one Task, they | 352 // If Sequences returned by GetWork() contain more than one Task, they |
| 341 // aren't empty after the worker pops Tasks from them and thus should be | 353 // aren't empty after the worker pops Tasks from them and thus should be |
| 342 // returned to EnqueueSequence(). | 354 // returned to EnqueueSequence(). |
| 343 if (TasksPerSequence() > 1) | 355 if (TasksPerSequence() > 1) |
| 344 EXPECT_EQ(CreatedSequences(), EnqueuedSequences()); | 356 EXPECT_EQ(CreatedSequences(), EnqueuedSequences()); |
| 345 else | 357 else |
| 346 EXPECT_TRUE(EnqueuedSequences().empty()); | 358 EXPECT_TRUE(EnqueuedSequences().empty()); |
| 347 } | 359 } |
| 348 } | 360 } |
| 349 | 361 |
| 350 INSTANTIATE_TEST_CASE_P(OneTaskPerSequence, | 362 INSTANTIATE_TEST_CASE_P(OneTaskPerSequence, |
| 351 TaskSchedulerWorkerTest, | 363 TaskSchedulerWorkerDoWorkTest, |
| 352 ::testing::Values(1)); | 364 ::testing::Values(1)); |
| 353 INSTANTIATE_TEST_CASE_P(TwoTasksPerSequence, | 365 INSTANTIATE_TEST_CASE_P(TwoTasksPerSequence, |
| 354 TaskSchedulerWorkerTest, | 366 TaskSchedulerWorkerDoWorkTest, |
| 355 ::testing::Values(2)); | 367 ::testing::Values(2)); |
| 356 | 368 |
| 357 namespace { | 369 namespace { |
| 358 | 370 |
| 359 class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate { | 371 class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate { |
| 360 public: | 372 public: |
| 361 ControllableDetachDelegate(TaskTracker* task_tracker) | 373 ControllableDetachDelegate(TaskTracker* task_tracker) |
| 362 : task_tracker_(task_tracker), | 374 : task_tracker_(task_tracker), |
| 363 work_processed_(WaitableEvent::ResetPolicy::MANUAL, | 375 work_processed_(WaitableEvent::ResetPolicy::MANUAL, |
| 364 WaitableEvent::InitialState::NOT_SIGNALED), | 376 WaitableEvent::InitialState::NOT_SIGNALED), |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 private: | 429 private: |
| 418 TaskTracker* const task_tracker_; | 430 TaskTracker* const task_tracker_; |
| 419 bool work_requested_ = false; | 431 bool work_requested_ = false; |
| 420 bool can_detach_ = false; | 432 bool can_detach_ = false; |
| 421 WaitableEvent work_processed_; | 433 WaitableEvent work_processed_; |
| 422 WaitableEvent detach_requested_; | 434 WaitableEvent detach_requested_; |
| 423 | 435 |
| 424 DISALLOW_COPY_AND_ASSIGN(ControllableDetachDelegate); | 436 DISALLOW_COPY_AND_ASSIGN(ControllableDetachDelegate); |
| 425 }; | 437 }; |
| 426 | 438 |
| 439 class TaskSchedulerWorkerTest : public testing::Test { |
| 440 public: |
| 441 TaskSchedulerWorkerTest() |
| 442 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) |
| 443 : task_tracker_(&service_message_loop_) |
| 444 #endif |
| 445 { |
| 446 } |
| 447 |
| 448 #if defined(OS_POSIX) && !defined(OS_NACL_SFI) |
| 449 private: |
| 450 MessageLoopForIO service_message_loop_; |
| 451 #endif |
| 452 |
| 453 protected: |
| 454 TaskTracker task_tracker_; |
| 455 |
| 456 private: |
| 457 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerTest); |
| 458 }; |
| 459 |
| 427 } // namespace | 460 } // namespace |
| 428 | 461 |
| 429 TEST(TaskSchedulerWorkerTest, WorkerDetaches) { | 462 TEST_F(TaskSchedulerWorkerTest, WorkerDetaches) { |
| 430 TaskTracker task_tracker; | |
| 431 // Will be owned by SchedulerWorker. | 463 // Will be owned by SchedulerWorker. |
| 432 ControllableDetachDelegate* delegate = | 464 ControllableDetachDelegate* delegate = |
| 433 new StrictMock<ControllableDetachDelegate>(&task_tracker); | 465 new StrictMock<ControllableDetachDelegate>(&task_tracker_); |
| 434 delegate->set_can_detach(true); | 466 delegate->set_can_detach(true); |
| 435 EXPECT_CALL(*delegate, OnMainEntry(_, TimeDelta::Max())); | 467 EXPECT_CALL(*delegate, OnMainEntry(_, TimeDelta::Max())); |
| 436 std::unique_ptr<SchedulerWorker> worker = | 468 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| 437 SchedulerWorker::Create( | 469 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker_, |
| 438 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, | 470 SchedulerWorker::InitialState::ALIVE); |
| 439 SchedulerWorker::InitialState::ALIVE); | |
| 440 worker->WakeUp(); | 471 worker->WakeUp(); |
| 441 delegate->WaitForWorkToRun(); | 472 delegate->WaitForWorkToRun(); |
| 442 Mock::VerifyAndClear(delegate); | 473 Mock::VerifyAndClear(delegate); |
| 443 delegate->WaitForDetachRequest(); | 474 delegate->WaitForDetachRequest(); |
| 444 // Sleep to give a chance for the detach to happen. A yield is too short. | 475 // Sleep to give a chance for the detach to happen. A yield is too short. |
| 445 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); | 476 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); |
| 446 ASSERT_FALSE(worker->ThreadAliveForTesting()); | 477 ASSERT_FALSE(worker->ThreadAliveForTesting()); |
| 447 } | 478 } |
| 448 | 479 |
| 449 TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) { | 480 TEST_F(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) { |
| 450 TaskTracker task_tracker; | |
| 451 // Will be owned by SchedulerWorker. | 481 // Will be owned by SchedulerWorker. |
| 452 ControllableDetachDelegate* delegate = | 482 ControllableDetachDelegate* delegate = |
| 453 new StrictMock<ControllableDetachDelegate>(&task_tracker); | 483 new StrictMock<ControllableDetachDelegate>(&task_tracker_); |
| 454 delegate->set_can_detach(true); | 484 delegate->set_can_detach(true); |
| 455 EXPECT_CALL(*delegate, OnMainEntry(_, TimeDelta::Max())); | 485 EXPECT_CALL(*delegate, OnMainEntry(_, TimeDelta::Max())); |
| 456 std::unique_ptr<SchedulerWorker> worker = | 486 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| 457 SchedulerWorker::Create( | 487 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker_, |
| 458 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, | 488 SchedulerWorker::InitialState::ALIVE); |
| 459 SchedulerWorker::InitialState::ALIVE); | |
| 460 worker->WakeUp(); | 489 worker->WakeUp(); |
| 461 delegate->WaitForWorkToRun(); | 490 delegate->WaitForWorkToRun(); |
| 462 Mock::VerifyAndClear(delegate); | 491 Mock::VerifyAndClear(delegate); |
| 463 delegate->WaitForDetachRequest(); | 492 delegate->WaitForDetachRequest(); |
| 464 // Sleep to give a chance for the detach to happen. A yield is too short. | 493 // Sleep to give a chance for the detach to happen. A yield is too short. |
| 465 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); | 494 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); |
| 466 ASSERT_FALSE(worker->ThreadAliveForTesting()); | 495 ASSERT_FALSE(worker->ThreadAliveForTesting()); |
| 467 | 496 |
| 468 delegate->ResetState(); | 497 delegate->ResetState(); |
| 469 delegate->set_can_detach(false); | 498 delegate->set_can_detach(false); |
| 470 // When SchedulerWorker recreates its thread, expect OnMainEntry() to be | 499 // When SchedulerWorker recreates its thread, expect OnMainEntry() to be |
| 471 // called with a detach duration which is not TimeDelta::Max(). | 500 // called with a detach duration which is not TimeDelta::Max(). |
| 472 EXPECT_CALL(*delegate, OnMainEntry(worker.get(), Ne(TimeDelta::Max()))); | 501 EXPECT_CALL(*delegate, OnMainEntry(worker.get(), Ne(TimeDelta::Max()))); |
| 473 worker->WakeUp(); | 502 worker->WakeUp(); |
| 474 delegate->WaitForWorkToRun(); | 503 delegate->WaitForWorkToRun(); |
| 475 Mock::VerifyAndClear(delegate); | 504 Mock::VerifyAndClear(delegate); |
| 476 delegate->WaitForDetachRequest(); | 505 delegate->WaitForDetachRequest(); |
| 477 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); | 506 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); |
| 478 ASSERT_TRUE(worker->ThreadAliveForTesting()); | 507 ASSERT_TRUE(worker->ThreadAliveForTesting()); |
| 479 worker->JoinForTesting(); | 508 worker->JoinForTesting(); |
| 480 } | 509 } |
| 481 | 510 |
| 482 TEST(TaskSchedulerWorkerTest, CreateDetached) { | 511 TEST_F(TaskSchedulerWorkerTest, CreateDetached) { |
| 483 TaskTracker task_tracker; | |
| 484 // Will be owned by SchedulerWorker. | 512 // Will be owned by SchedulerWorker. |
| 485 ControllableDetachDelegate* delegate = | 513 ControllableDetachDelegate* delegate = |
| 486 new StrictMock<ControllableDetachDelegate>(&task_tracker); | 514 new StrictMock<ControllableDetachDelegate>(&task_tracker_); |
| 487 std::unique_ptr<SchedulerWorker> worker = | 515 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| 488 SchedulerWorker::Create( | 516 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker_, |
| 489 ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, | 517 SchedulerWorker::InitialState::DETACHED); |
| 490 SchedulerWorker::InitialState::DETACHED); | |
| 491 ASSERT_FALSE(worker->ThreadAliveForTesting()); | 518 ASSERT_FALSE(worker->ThreadAliveForTesting()); |
| 492 EXPECT_CALL(*delegate, OnMainEntry(worker.get(), TimeDelta::Max())); | 519 EXPECT_CALL(*delegate, OnMainEntry(worker.get(), TimeDelta::Max())); |
| 493 worker->WakeUp(); | 520 worker->WakeUp(); |
| 494 delegate->WaitForWorkToRun(); | 521 delegate->WaitForWorkToRun(); |
| 495 Mock::VerifyAndClear(delegate); | 522 Mock::VerifyAndClear(delegate); |
| 496 delegate->WaitForDetachRequest(); | 523 delegate->WaitForDetachRequest(); |
| 497 ASSERT_TRUE(worker->ThreadAliveForTesting()); | 524 ASSERT_TRUE(worker->ThreadAliveForTesting()); |
| 498 worker->JoinForTesting(); | 525 worker->JoinForTesting(); |
| 499 } | 526 } |
| 500 | 527 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 SchedulerLock expected_thread_priority_lock_; | 568 SchedulerLock expected_thread_priority_lock_; |
| 542 | 569 |
| 543 // Expected thread priority for the next call to OnMainEntry() or GetWork(). | 570 // Expected thread priority for the next call to OnMainEntry() or GetWork(). |
| 544 ThreadPriority expected_thread_priority_; | 571 ThreadPriority expected_thread_priority_; |
| 545 | 572 |
| 546 DISALLOW_COPY_AND_ASSIGN(ExpectThreadPriorityDelegate); | 573 DISALLOW_COPY_AND_ASSIGN(ExpectThreadPriorityDelegate); |
| 547 }; | 574 }; |
| 548 | 575 |
| 549 } // namespace | 576 } // namespace |
| 550 | 577 |
| 551 TEST(TaskSchedulerWorkerTest, BumpPriorityOfAliveThreadDuringShutdown) { | 578 TEST_F(TaskSchedulerWorkerTest, BumpPriorityOfAliveThreadDuringShutdown) { |
| 552 TaskTracker task_tracker; | |
| 553 | |
| 554 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( | 579 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( |
| 555 new ExpectThreadPriorityDelegate); | 580 new ExpectThreadPriorityDelegate); |
| 556 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); | 581 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); |
| 557 delegate_raw->SetExpectedThreadPriority( | 582 delegate_raw->SetExpectedThreadPriority( |
| 558 PlatformThread::CanIncreaseCurrentThreadPriority() | 583 PlatformThread::CanIncreaseCurrentThreadPriority() |
| 559 ? ThreadPriority::BACKGROUND | 584 ? ThreadPriority::BACKGROUND |
| 560 : ThreadPriority::NORMAL); | 585 : ThreadPriority::NORMAL); |
| 561 | 586 |
| 562 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( | 587 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| 563 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, | 588 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker_, |
| 564 SchedulerWorker::InitialState::ALIVE); | 589 SchedulerWorker::InitialState::ALIVE); |
| 565 | 590 |
| 566 // Verify that the initial thread priority is BACKGROUND (or NORMAL if thread | 591 // Verify that the initial thread priority is BACKGROUND (or NORMAL if thread |
| 567 // priority can't be increased). | 592 // priority can't be increased). |
| 568 worker->WakeUp(); | 593 worker->WakeUp(); |
| 569 delegate_raw->WaitForPriorityVerifiedInGetWork(); | 594 delegate_raw->WaitForPriorityVerifiedInGetWork(); |
| 570 | 595 |
| 571 // Verify that the thread priority is bumped to NORMAL during shutdown. | 596 // Verify that the thread priority is bumped to NORMAL during shutdown. |
| 572 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); | 597 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); |
| 573 task_tracker.SetHasShutdownStartedForTesting(); | 598 task_tracker_.SetHasShutdownStartedForTesting(); |
| 574 worker->WakeUp(); | 599 worker->WakeUp(); |
| 575 delegate_raw->WaitForPriorityVerifiedInGetWork(); | 600 delegate_raw->WaitForPriorityVerifiedInGetWork(); |
| 576 | 601 |
| 577 worker->JoinForTesting(); | 602 worker->JoinForTesting(); |
| 578 } | 603 } |
| 579 | 604 |
| 580 TEST(TaskSchedulerWorkerTest, BumpPriorityOfDetachedThreadDuringShutdown) { | 605 TEST_F(TaskSchedulerWorkerTest, BumpPriorityOfDetachedThreadDuringShutdown) { |
| 581 TaskTracker task_tracker; | |
| 582 | |
| 583 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( | 606 std::unique_ptr<ExpectThreadPriorityDelegate> delegate( |
| 584 new ExpectThreadPriorityDelegate); | 607 new ExpectThreadPriorityDelegate); |
| 585 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); | 608 ExpectThreadPriorityDelegate* delegate_raw = delegate.get(); |
| 586 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); | 609 delegate_raw->SetExpectedThreadPriority(ThreadPriority::NORMAL); |
| 587 | 610 |
| 588 // Create a DETACHED thread. | 611 // Create a DETACHED thread. |
| 589 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( | 612 std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| 590 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker, | 613 ThreadPriority::BACKGROUND, std::move(delegate), &task_tracker_, |
| 591 SchedulerWorker::InitialState::DETACHED); | 614 SchedulerWorker::InitialState::DETACHED); |
| 592 | 615 |
| 593 // Pretend that shutdown has started. | 616 // Pretend that shutdown has started. |
| 594 task_tracker.SetHasShutdownStartedForTesting(); | 617 task_tracker_.SetHasShutdownStartedForTesting(); |
| 595 | 618 |
| 596 // Wake up the thread and verify that its priority is NORMAL when | 619 // Wake up the thread and verify that its priority is NORMAL when |
| 597 // OnMainEntry() and GetWork() are called. | 620 // OnMainEntry() and GetWork() are called. |
| 598 worker->WakeUp(); | 621 worker->WakeUp(); |
| 599 delegate_raw->WaitForPriorityVerifiedInGetWork(); | 622 delegate_raw->WaitForPriorityVerifiedInGetWork(); |
| 600 | 623 |
| 601 worker->JoinForTesting(); | 624 worker->JoinForTesting(); |
| 602 } | 625 } |
| 603 | 626 |
| 604 } // namespace | 627 } // namespace |
| 605 } // namespace internal | 628 } // namespace internal |
| 606 } // namespace base | 629 } // namespace base |
| OLD | NEW |