| 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> |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 class SchedulerWorkerDefaultDelegate : public SchedulerWorker::Delegate { | 39 class SchedulerWorkerDefaultDelegate : public SchedulerWorker::Delegate { |
| 40 public: | 40 public: |
| 41 SchedulerWorkerDefaultDelegate() = default; | 41 SchedulerWorkerDefaultDelegate() = default; |
| 42 | 42 |
| 43 // SchedulerWorker::Delegate: | 43 // SchedulerWorker::Delegate: |
| 44 void OnMainEntry(SchedulerWorker* worker, | 44 void OnMainEntry(SchedulerWorker* worker, |
| 45 const TimeDelta& detach_duration) override {} | 45 const TimeDelta& detach_duration) override {} |
| 46 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { | 46 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { |
| 47 return nullptr; | 47 return nullptr; |
| 48 } | 48 } |
| 49 void DidRunTask(const Task* task, const TimeDelta& task_latency) override { | 49 void DidRunTaskWithPriority(TaskPriority task_priority, |
| 50 ADD_FAILURE() << "Unexpected call to DidRunTask()"; | 50 const TimeDelta& task_latency) override { |
| 51 ADD_FAILURE() << "Unexpected call to DidRunTaskWithPriority()"; |
| 51 } | 52 } |
| 52 void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override { | 53 void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override { |
| 53 ADD_FAILURE() << "Unexpected call to ReEnqueueSequence()"; | 54 ADD_FAILURE() << "Unexpected call to ReEnqueueSequence()"; |
| 54 } | 55 } |
| 55 TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } | 56 TimeDelta GetSleepTimeout() override { return TimeDelta::Max(); } |
| 56 bool CanDetach(SchedulerWorker* worker) override { return false; } | 57 bool CanDetach(SchedulerWorker* worker) override { return false; } |
| 57 | 58 |
| 58 private: | 59 private: |
| 59 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDefaultDelegate); | 60 DISALLOW_COPY_AND_ASSIGN(SchedulerWorkerDefaultDelegate); |
| 60 }; | 61 }; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 | 120 |
| 120 std::unique_ptr<SchedulerWorker> worker_; | 121 std::unique_ptr<SchedulerWorker> worker_; |
| 121 | 122 |
| 122 private: | 123 private: |
| 123 class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate { | 124 class TestSchedulerWorkerDelegate : public SchedulerWorkerDefaultDelegate { |
| 124 public: | 125 public: |
| 125 TestSchedulerWorkerDelegate(TaskSchedulerWorkerTest* outer) | 126 TestSchedulerWorkerDelegate(TaskSchedulerWorkerTest* outer) |
| 126 : outer_(outer) {} | 127 : outer_(outer) {} |
| 127 | 128 |
| 128 ~TestSchedulerWorkerDelegate() override { | 129 ~TestSchedulerWorkerDelegate() override { |
| 129 EXPECT_FALSE(IsCallToDidRunTaskExpected()); | 130 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected()); |
| 130 } | 131 } |
| 131 | 132 |
| 132 // SchedulerWorker::Delegate: | 133 // SchedulerWorker::Delegate: |
| 133 void OnMainEntry(SchedulerWorker* worker, | 134 void OnMainEntry(SchedulerWorker* worker, |
| 134 const TimeDelta& detach_duration) override { | 135 const TimeDelta& detach_duration) override { |
| 135 outer_->worker_set_.Wait(); | 136 outer_->worker_set_.Wait(); |
| 136 EXPECT_EQ(outer_->worker_.get(), worker); | 137 EXPECT_EQ(outer_->worker_.get(), worker); |
| 137 EXPECT_FALSE(IsCallToDidRunTaskExpected()); | 138 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected()); |
| 138 | 139 |
| 139 // Without synchronization, OnMainEntry() could be called twice without | 140 // Without synchronization, OnMainEntry() could be called twice without |
| 140 // generating an error. | 141 // generating an error. |
| 141 AutoSchedulerLock auto_lock(outer_->lock_); | 142 AutoSchedulerLock auto_lock(outer_->lock_); |
| 142 EXPECT_FALSE(outer_->main_entry_called_.IsSignaled()); | 143 EXPECT_FALSE(outer_->main_entry_called_.IsSignaled()); |
| 143 outer_->main_entry_called_.Signal(); | 144 outer_->main_entry_called_.Signal(); |
| 144 } | 145 } |
| 145 | 146 |
| 146 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { | 147 scoped_refptr<Sequence> GetWork(SchedulerWorker* worker) override { |
| 147 EXPECT_FALSE(IsCallToDidRunTaskExpected()); | 148 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected()); |
| 148 EXPECT_EQ(outer_->worker_.get(), worker); | 149 EXPECT_EQ(outer_->worker_.get(), worker); |
| 149 | 150 |
| 150 { | 151 { |
| 151 AutoSchedulerLock auto_lock(outer_->lock_); | 152 AutoSchedulerLock auto_lock(outer_->lock_); |
| 152 | 153 |
| 153 // Increment the number of times that this method has been called. | 154 // Increment the number of times that this method has been called. |
| 154 ++outer_->num_get_work_; | 155 ++outer_->num_get_work_; |
| 155 outer_->num_get_work_cv_->Signal(); | 156 outer_->num_get_work_cv_->Signal(); |
| 156 | 157 |
| 157 // Verify that this method isn't called more times than expected. | 158 // Verify that this method isn't called more times than expected. |
| 158 EXPECT_LE(outer_->num_get_work_, outer_->max_get_work_); | 159 EXPECT_LE(outer_->num_get_work_, outer_->max_get_work_); |
| 159 | 160 |
| 160 // Check if a Sequence should be returned. | 161 // Check if a Sequence should be returned. |
| 161 if (outer_->num_sequences_to_create_ == 0) | 162 if (outer_->num_sequences_to_create_ == 0) |
| 162 return nullptr; | 163 return nullptr; |
| 163 --outer_->num_sequences_to_create_; | 164 --outer_->num_sequences_to_create_; |
| 164 } | 165 } |
| 165 | 166 |
| 166 // Create a Sequence with TasksPerSequence() Tasks. | 167 // Create a Sequence with TasksPerSequence() Tasks. |
| 167 scoped_refptr<Sequence> sequence(new Sequence); | 168 scoped_refptr<Sequence> sequence(new Sequence); |
| 168 for (size_t i = 0; i < outer_->TasksPerSequence(); ++i) { | 169 for (size_t i = 0; i < outer_->TasksPerSequence(); ++i) { |
| 169 std::unique_ptr<Task> task(new Task( | 170 std::unique_ptr<Task> task(new Task( |
| 170 FROM_HERE, Bind(&TaskSchedulerWorkerTest::RunTaskCallback, | 171 FROM_HERE, Bind(&TaskSchedulerWorkerTest::RunTaskCallback, |
| 171 Unretained(outer_)), | 172 Unretained(outer_)), |
| 172 TaskTraits(), TimeDelta())); | 173 TaskTraits(), TimeDelta())); |
| 173 EXPECT_TRUE(outer_->task_tracker_.WillPostTask(task.get())); | 174 EXPECT_TRUE(outer_->task_tracker_.WillPostTask(task.get())); |
| 174 sequence->PushTask(std::move(task)); | 175 sequence->PushTask(std::move(task)); |
| 175 } | 176 } |
| 176 | 177 |
| 177 ExpectCallToDidRunTask(sequence->PeekTask()); | 178 ExpectCallToDidRunTaskWithPriority(sequence->PeekTaskTraits().priority()); |
| 178 | 179 |
| 179 { | 180 { |
| 180 // Add the Sequence to the vector of created Sequences. | 181 // Add the Sequence to the vector of created Sequences. |
| 181 AutoSchedulerLock auto_lock(outer_->lock_); | 182 AutoSchedulerLock auto_lock(outer_->lock_); |
| 182 outer_->created_sequences_.push_back(sequence); | 183 outer_->created_sequences_.push_back(sequence); |
| 183 } | 184 } |
| 184 | 185 |
| 185 return sequence; | 186 return sequence; |
| 186 } | 187 } |
| 187 | 188 |
| 188 void DidRunTask(const Task* task, const TimeDelta& task_latency) override { | 189 void DidRunTaskWithPriority(TaskPriority task_priority, |
| 189 AutoSchedulerLock auto_lock(expect_did_run_task_lock_); | 190 const TimeDelta& task_latency) override { |
| 190 EXPECT_EQ(expect_did_run_task_, task); | 191 AutoSchedulerLock auto_lock(expect_did_run_task_with_priority_lock_); |
| 191 expect_did_run_task_ = nullptr; | 192 EXPECT_TRUE(expect_did_run_task_with_priority_); |
| 193 EXPECT_EQ(expected_task_priority_, task_priority); |
| 192 EXPECT_FALSE(task_latency.is_max()); | 194 EXPECT_FALSE(task_latency.is_max()); |
| 195 expect_did_run_task_with_priority_ = false; |
| 193 } | 196 } |
| 194 | 197 |
| 195 // This override verifies that |sequence| contains the expected number of | 198 // This override verifies that |sequence| contains the expected number of |
| 196 // Tasks and adds it to |enqueued_sequences_|. Unlike a normal | 199 // Tasks and adds it to |enqueued_sequences_|. Unlike a normal |
| 197 // EnqueueSequence implementation, it doesn't reinsert |sequence| into a | 200 // EnqueueSequence implementation, it doesn't reinsert |sequence| into a |
| 198 // queue for further execution. | 201 // queue for further execution. |
| 199 void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override { | 202 void ReEnqueueSequence(scoped_refptr<Sequence> sequence) override { |
| 200 EXPECT_FALSE(IsCallToDidRunTaskExpected()); | 203 EXPECT_FALSE(IsCallToDidRunTaskWithPriorityExpected()); |
| 201 EXPECT_GT(outer_->TasksPerSequence(), 1U); | 204 EXPECT_GT(outer_->TasksPerSequence(), 1U); |
| 202 | 205 |
| 203 // Verify that |sequence| contains TasksPerSequence() - 1 Tasks. | 206 // Verify that |sequence| contains TasksPerSequence() - 1 Tasks. |
| 204 for (size_t i = 0; i < outer_->TasksPerSequence() - 1; ++i) { | 207 for (size_t i = 0; i < outer_->TasksPerSequence() - 1; ++i) { |
| 205 EXPECT_TRUE(sequence->PeekTask()); | 208 EXPECT_TRUE(sequence->TakeTask()); |
| 206 sequence->PopTask(); | 209 EXPECT_EQ(i == outer_->TasksPerSequence() - 2, sequence->Pop()); |
| 207 } | 210 } |
| 208 EXPECT_FALSE(sequence->PeekTask()); | |
| 209 | 211 |
| 210 // Add |sequence| to |re_enqueued_sequences_|. | 212 // Add |sequence| to |re_enqueued_sequences_|. |
| 211 AutoSchedulerLock auto_lock(outer_->lock_); | 213 AutoSchedulerLock auto_lock(outer_->lock_); |
| 212 outer_->re_enqueued_sequences_.push_back(std::move(sequence)); | 214 outer_->re_enqueued_sequences_.push_back(std::move(sequence)); |
| 213 EXPECT_LE(outer_->re_enqueued_sequences_.size(), | 215 EXPECT_LE(outer_->re_enqueued_sequences_.size(), |
| 214 outer_->created_sequences_.size()); | 216 outer_->created_sequences_.size()); |
| 215 } | 217 } |
| 216 | 218 |
| 217 private: | 219 private: |
| 218 // Expect a call to DidRunTask() with |task| as argument before the next | 220 // Expect a call to DidRunTaskWithPriority() with |task_priority| as |
| 219 // call to any other method of this delegate. | 221 // argument before the next call to any other method of this delegate. |
| 220 void ExpectCallToDidRunTask(const Task* task) { | 222 void ExpectCallToDidRunTaskWithPriority(TaskPriority task_priority) { |
| 221 AutoSchedulerLock auto_lock(expect_did_run_task_lock_); | 223 AutoSchedulerLock auto_lock(expect_did_run_task_with_priority_lock_); |
| 222 expect_did_run_task_ = task; | 224 expect_did_run_task_with_priority_ = true; |
| 225 expected_task_priority_ = task_priority; |
| 223 } | 226 } |
| 224 | 227 |
| 225 bool IsCallToDidRunTaskExpected() const { | 228 bool IsCallToDidRunTaskWithPriorityExpected() const { |
| 226 AutoSchedulerLock auto_lock(expect_did_run_task_lock_); | 229 AutoSchedulerLock auto_lock(expect_did_run_task_with_priority_lock_); |
| 227 return expect_did_run_task_ != nullptr; | 230 return expect_did_run_task_with_priority_; |
| 228 } | 231 } |
| 229 | 232 |
| 230 TaskSchedulerWorkerTest* outer_; | 233 TaskSchedulerWorkerTest* outer_; |
| 231 | 234 |
| 232 // Synchronizes access to |expect_did_run_task_|. | 235 // Synchronizes access to |expect_did_run_task_with_priority_| and |
| 233 mutable SchedulerLock expect_did_run_task_lock_; | 236 // |expected_task_priority_|. |
| 237 mutable SchedulerLock expect_did_run_task_with_priority_lock_; |
| 234 | 238 |
| 235 // Expected task for the next call to DidRunTask(). DidRunTask() should not | 239 // Whether the next method called on this delegate should be |
| 236 // be called when this is nullptr. No method other than DidRunTask() should | 240 // DidRunTaskWithPriority(). |
| 237 // be called on this delegate when this is not nullptr. | 241 bool expect_did_run_task_with_priority_ = false; |
| 238 const Task* expect_did_run_task_ = nullptr; | 242 |
| 243 // Expected priority for the next call to DidRunTaskWithPriority(). |
| 244 TaskPriority expected_task_priority_ = TaskPriority::BACKGROUND; |
| 239 }; | 245 }; |
| 240 | 246 |
| 241 void RunTaskCallback() { | 247 void RunTaskCallback() { |
| 242 AutoSchedulerLock auto_lock(lock_); | 248 AutoSchedulerLock auto_lock(lock_); |
| 243 ++num_run_tasks_; | 249 ++num_run_tasks_; |
| 244 EXPECT_LE(num_run_tasks_, created_sequences_.size()); | 250 EXPECT_LE(num_run_tasks_, created_sequences_.size()); |
| 245 } | 251 } |
| 246 | 252 |
| 247 TaskTracker task_tracker_; | 253 TaskTracker task_tracker_; |
| 248 | 254 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 work_requested_ = true; | 383 work_requested_ = true; |
| 378 scoped_refptr<Sequence> sequence(new Sequence); | 384 scoped_refptr<Sequence> sequence(new Sequence); |
| 379 std::unique_ptr<Task> task(new Task( | 385 std::unique_ptr<Task> task(new Task( |
| 380 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&work_processed_)), | 386 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&work_processed_)), |
| 381 TaskTraits(), TimeDelta())); | 387 TaskTraits(), TimeDelta())); |
| 382 EXPECT_TRUE(task_tracker_->WillPostTask(task.get())); | 388 EXPECT_TRUE(task_tracker_->WillPostTask(task.get())); |
| 383 sequence->PushTask(std::move(task)); | 389 sequence->PushTask(std::move(task)); |
| 384 return sequence; | 390 return sequence; |
| 385 } | 391 } |
| 386 | 392 |
| 387 void DidRunTask(const Task* task, const TimeDelta& task_latency) override {} | 393 void DidRunTaskWithPriority(TaskPriority task, |
| 394 const TimeDelta& task_latency) override {} |
| 388 | 395 |
| 389 bool CanDetach(SchedulerWorker* worker) override { | 396 bool CanDetach(SchedulerWorker* worker) override { |
| 390 detach_requested_.Signal(); | 397 detach_requested_.Signal(); |
| 391 return can_detach_; | 398 return can_detach_; |
| 392 } | 399 } |
| 393 | 400 |
| 394 void WaitForWorkToRun() { | 401 void WaitForWorkToRun() { |
| 395 work_processed_.Wait(); | 402 work_processed_.Wait(); |
| 396 } | 403 } |
| 397 | 404 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 // OnMainEntry() and GetWork() are called. | 597 // OnMainEntry() and GetWork() are called. |
| 591 worker->WakeUp(); | 598 worker->WakeUp(); |
| 592 delegate_raw->WaitForPriorityVerifiedInGetWork(); | 599 delegate_raw->WaitForPriorityVerifiedInGetWork(); |
| 593 | 600 |
| 594 worker->JoinForTesting(); | 601 worker->JoinForTesting(); |
| 595 } | 602 } |
| 596 | 603 |
| 597 } // namespace | 604 } // namespace |
| 598 } // namespace internal | 605 } // namespace internal |
| 599 } // namespace base | 606 } // namespace base |
| OLD | NEW |