Chromium Code Reviews| 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_thread.h" | 5 #include "base/task_scheduler/scheduler_worker_thread.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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 // returned by GetWork(). | 87 // returned by GetWork(). |
| 88 EXPECT_EQ(created_sequences_.size(), num_run_tasks_); | 88 EXPECT_EQ(created_sequences_.size(), num_run_tasks_); |
| 89 } | 89 } |
| 90 | 90 |
| 91 void SetNumSequencesToCreate(size_t num_sequences_to_create) { | 91 void SetNumSequencesToCreate(size_t num_sequences_to_create) { |
| 92 AutoSchedulerLock auto_lock(lock_); | 92 AutoSchedulerLock auto_lock(lock_); |
| 93 EXPECT_EQ(0U, num_sequences_to_create_); | 93 EXPECT_EQ(0U, num_sequences_to_create_); |
| 94 num_sequences_to_create_ = num_sequences_to_create; | 94 num_sequences_to_create_ = num_sequences_to_create; |
| 95 } | 95 } |
| 96 | 96 |
| 97 size_t NumGetWork() const { | 97 void SetMaxGetWork(size_t max_get_work) { |
| 98 AutoSchedulerLock auto_lock(lock_); | 98 AutoSchedulerLock auto_lock(lock_); |
| 99 return num_get_work_; | 99 max_get_work_ = max_get_work; |
| 100 } | 100 } |
| 101 | 101 |
| 102 std::unique_ptr<SchedulerWorkerThread> worker_thread_; | 102 std::unique_ptr<SchedulerWorkerThread> worker_thread_; |
| 103 | 103 |
| 104 private: | 104 private: |
| 105 // SchedulerWorkerThreadDelegate: | 105 // SchedulerWorkerThreadDelegate: |
| 106 void OnMainEntry() override { | 106 void OnMainEntry() override { |
| 107 AutoSchedulerLock auto_lock(lock_); | 107 AutoSchedulerLock auto_lock(lock_); |
| 108 ++num_main_entry_; | 108 ++num_main_entry_; |
| 109 num_main_entry_cv_->Signal(); | 109 num_main_entry_cv_->Signal(); |
| 110 } | 110 } |
| 111 | 111 |
| 112 void OnMainExit() override { | 112 void OnMainExit() override { |
| 113 AutoSchedulerLock auto_lock(lock_); | 113 AutoSchedulerLock auto_lock(lock_); |
| 114 ++num_main_exit_; | 114 ++num_main_exit_; |
| 115 } | 115 } |
| 116 | 116 |
| 117 scoped_refptr<Sequence> GetWork() override { | 117 scoped_refptr<Sequence> GetWork() override { |
| 118 { | 118 { |
| 119 AutoSchedulerLock auto_lock(lock_); | 119 AutoSchedulerLock auto_lock(lock_); |
| 120 | 120 |
| 121 // Increment the number of times that this method has been called. | 121 // Increment the number of times that this method has been called. |
| 122 ++num_get_work_; | 122 ++num_get_work_; |
| 123 num_get_work_cv_->Signal(); | 123 num_get_work_cv_->Signal(); |
| 124 | 124 |
| 125 // Verify that this method isn't called more times than expected. | |
| 126 EXPECT_LE(num_get_work_, max_get_work_); | |
| 127 | |
| 125 // Check if a Sequence should be returned. | 128 // Check if a Sequence should be returned. |
| 126 if (num_sequences_to_create_ == 0) | 129 if (num_sequences_to_create_ == 0) |
| 127 return nullptr; | 130 return nullptr; |
| 128 --num_sequences_to_create_; | 131 --num_sequences_to_create_; |
| 129 } | 132 } |
| 130 | 133 |
| 131 // Create a Sequence that contains 1 Task. | 134 // Create a Sequence that contains 1 Task. |
| 132 scoped_refptr<Sequence> sequence(new Sequence); | 135 scoped_refptr<Sequence> sequence(new Sequence); |
| 133 task_tracker_.PostTask( | 136 task_tracker_.PostTask( |
| 134 Bind(IgnoreResult(&Sequence::PushTask), Unretained(sequence.get())), | 137 Bind(IgnoreResult(&Sequence::PushTask), Unretained(sequence.get())), |
| 135 WrapUnique(new Task( | 138 WrapUnique(new Task( |
| 136 FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback, | 139 FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback, |
| 137 Unretained(this)), | 140 Unretained(this)), |
| 138 TaskTraits()))); | 141 TaskTraits()))); |
| 139 | 142 |
| 140 { | 143 { |
| 141 // Add the Sequence to the vector of created Sequences. | 144 // Add the Sequence to the vector of created Sequences. |
| 142 AutoSchedulerLock auto_lock(lock_); | 145 AutoSchedulerLock auto_lock(lock_); |
| 143 created_sequences_.push_back(sequence); | 146 created_sequences_.push_back(sequence); |
| 144 } | 147 } |
| 145 | 148 |
| 146 return sequence; | 149 return sequence; |
| 147 } | 150 } |
| 148 | 151 |
| 149 // Called after the SchedulerWorkerThread has tried to run a Task from | 152 // Called after the SchedulerWorkerThread has tried to run a Task from |
| 150 // |sequence| (a TaskTracker might have prevented the Task from running). | 153 // |sequence| (a TaskTracker might have prevented the Task from running). |
| 151 void RanTaskFromSequence(scoped_refptr<Sequence> sequence) override { | 154 void RanTaskFromSequence(scoped_refptr<Sequence> sequence) override { |
| 152 AutoSchedulerLock auto_lock(lock_); | 155 AutoSchedulerLock auto_lock(lock_); |
| 153 run_sequences_.push_back(std::move(sequence)); | 156 run_sequences_.push_back(std::move(sequence)); |
| 157 EXPECT_LE(run_sequences_.size(), created_sequences_.size()); | |
| 154 run_sequences_cv_->Signal(); | 158 run_sequences_cv_->Signal(); |
| 155 } | 159 } |
| 156 | 160 |
| 157 void RunTaskCallback() { | 161 void RunTaskCallback() { |
| 158 AutoSchedulerLock auto_lock(lock_); | 162 AutoSchedulerLock auto_lock(lock_); |
| 159 ++num_run_tasks_; | 163 ++num_run_tasks_; |
| 164 EXPECT_LE(num_run_tasks_, created_sequences_.size()); | |
| 160 } | 165 } |
| 161 | 166 |
| 162 TaskTracker task_tracker_; | 167 TaskTracker task_tracker_; |
| 163 | 168 |
| 164 // Synchronizes access to all members below. | 169 // Synchronizes access to all members below. |
| 165 mutable SchedulerLock lock_; | 170 mutable SchedulerLock lock_; |
| 166 | 171 |
| 167 // Number of times that OnMainEntry() has been called. | 172 // Number of times that OnMainEntry() has been called. |
| 168 size_t num_main_entry_ = 0; | 173 size_t num_main_entry_ = 0; |
| 169 | 174 |
| 170 // Condition variable signaled when |num_main_entry_| is incremented. | 175 // Condition variable signaled when |num_main_entry_| is incremented. |
| 171 std::unique_ptr<ConditionVariable> num_main_entry_cv_; | 176 std::unique_ptr<ConditionVariable> num_main_entry_cv_; |
| 172 | 177 |
| 173 // Number of times that OnMainExit() has been called. | 178 // Number of times that OnMainExit() has been called. |
| 174 size_t num_main_exit_ = 0; | 179 size_t num_main_exit_ = 0; |
| 175 | 180 |
| 176 // Number of Sequences that should be created by GetWork(). When this | 181 // Number of Sequences that should be created by GetWork(). When this |
| 177 // is 0, GetWork() returns nullptr. | 182 // is 0, GetWork() returns nullptr. |
| 178 size_t num_sequences_to_create_ = 0; | 183 size_t num_sequences_to_create_ = 0; |
| 179 | 184 |
| 180 // Number of times that GetWork() has been called. | 185 // Number of times that GetWork() has been called. |
| 181 size_t num_get_work_ = 0; | 186 size_t num_get_work_ = 0; |
| 182 | 187 |
| 188 // Maximum number of times that GetWork() can be called. | |
| 189 size_t max_get_work_ = 0; | |
| 190 | |
| 183 // Condition variable signaled when |num_get_work_| is incremented. | 191 // Condition variable signaled when |num_get_work_| is incremented. |
| 184 std::unique_ptr<ConditionVariable> num_get_work_cv_; | 192 std::unique_ptr<ConditionVariable> num_get_work_cv_; |
| 185 | 193 |
| 186 // Sequences created by GetWork(). | 194 // Sequences created by GetWork(). |
| 187 std::vector<scoped_refptr<Sequence>> created_sequences_; | 195 std::vector<scoped_refptr<Sequence>> created_sequences_; |
| 188 | 196 |
| 189 // Sequences passed to RanTaskFromSequence(). | 197 // Sequences passed to RanTaskFromSequence(). |
| 190 std::vector<scoped_refptr<Sequence>> run_sequences_; | 198 std::vector<scoped_refptr<Sequence>> run_sequences_; |
| 191 | 199 |
| 192 // Condition variable signaled when a Sequence is added to |run_sequences_|. | 200 // Condition variable signaled when a Sequence is added to |run_sequences_|. |
| 193 std::unique_ptr<ConditionVariable> run_sequences_cv_; | 201 std::unique_ptr<ConditionVariable> run_sequences_cv_; |
| 194 | 202 |
| 195 // Number of times that RunTaskCallback() has been called. | 203 // Number of times that RunTaskCallback() has been called. |
| 196 size_t num_run_tasks_ = 0; | 204 size_t num_run_tasks_ = 0; |
| 197 | 205 |
| 198 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadTest); | 206 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadTest); |
| 199 }; | 207 }; |
| 200 | 208 |
| 201 // Verify that when GetWork() continuously returns Sequences, all Tasks in these | 209 // Verify that when GetWork() continuously returns Sequences, all Tasks in these |
| 202 // Sequences run successfully. The SchedulerWorkerThread is woken up once. | 210 // Sequences run successfully. The test wakes up the SchedulerWorkerThread once. |
| 203 TEST_F(TaskSchedulerWorkerThreadTest, ContinousWork) { | 211 TEST_F(TaskSchedulerWorkerThreadTest, ContinuousWork) { |
| 204 // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to | 212 // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to |
| 205 // return nullptr. | 213 // return nullptr. |
| 206 SetNumSequencesToCreate(kNumSequencesPerTest); | 214 SetNumSequencesToCreate(kNumSequencesPerTest); |
| 207 | 215 |
| 216 // Expect |kNumSequencesPerTest| calls to GetWork() in which it returns a | |
| 217 // Sequence and 1 call in which its returns nullptr. | |
|
gab
2016/04/07 15:47:36
s/1/one/ (in comments err towards only using digit
fdoray
2016/04/07 22:17:16
Done.
| |
| 218 const size_t kExpectedNumGetWork = kNumSequencesPerTest + 1; | |
| 219 SetMaxGetWork(kExpectedNumGetWork); | |
| 220 | |
| 208 // Wake up |worker_thread_| and wait until it has run all the Tasks returned | 221 // Wake up |worker_thread_| and wait until it has run all the Tasks returned |
| 209 // by GetWork(). | 222 // by GetWork(). |
| 210 worker_thread_->WakeUp(); | 223 worker_thread_->WakeUp(); |
| 211 WaitForAllSequencesToRun(); | 224 WaitForAllSequencesToRun(); |
| 212 | 225 WaitForNumGetWork(kExpectedNumGetWork); |
| 213 // Expect |kNumSequencesPerTest| calls to GetWork() in which it returned a | |
| 214 // Sequence and 1 call in which it returned nullptr. | |
| 215 const size_t expected_num_get_work = kNumSequencesPerTest + 1; | |
| 216 WaitForNumGetWork(expected_num_get_work); | |
| 217 EXPECT_EQ(expected_num_get_work, NumGetWork()); | |
| 218 } | 226 } |
| 219 | 227 |
| 220 // Verify that when GetWork() alternates between returning a Sequence and | 228 // Verify that when GetWork() alternates between returning a Sequence and |
| 221 // returning nullptr, all Tasks in the returned Sequences run successfully. The | 229 // returning nullptr, all Tasks in the returned Sequences run successfully. The |
| 222 // SchedulerWorkerThread is woken up once for each Sequence. | 230 // test wakes up the SchedulerWorkerThread once for each Sequence. |
| 223 TEST_F(TaskSchedulerWorkerThreadTest, IntermittentWork) { | 231 TEST_F(TaskSchedulerWorkerThreadTest, IntermittentWork) { |
| 224 for (size_t i = 0; i < kNumSequencesPerTest; ++i) { | 232 for (size_t i = 0; i < kNumSequencesPerTest; ++i) { |
| 225 // Set GetWork() to return 1 Sequence before starting to return | 233 // Set GetWork() to return 1 Sequence before starting to return |
| 226 // nullptr. | 234 // nullptr. |
| 227 SetNumSequencesToCreate(1); | 235 SetNumSequencesToCreate(1); |
| 228 | 236 |
| 237 // Expect |i + 1| calls to GetWork() in which it returns a Sequence and | |
| 238 // |i + 1| calls in which it returns nullptr. | |
| 239 const size_t expected_num_get_work = 2 * (i + 1); | |
| 240 SetMaxGetWork(expected_num_get_work); | |
| 241 | |
| 229 // Wake up |worker_thread_| and wait until it has run all the Tasks returned | 242 // Wake up |worker_thread_| and wait until it has run all the Tasks returned |
| 230 // by GetWork(). | 243 // by GetWork(). |
| 231 worker_thread_->WakeUp(); | 244 worker_thread_->WakeUp(); |
| 232 WaitForAllSequencesToRun(); | 245 WaitForAllSequencesToRun(); |
| 233 | |
| 234 // Expect |i| calls to GetWork() in which it returned a Sequence and | |
| 235 // |i| calls in which it returned nullptr. | |
| 236 const size_t expected_num_get_work = 2 * (i + 1); | |
| 237 WaitForNumGetWork(expected_num_get_work); | 246 WaitForNumGetWork(expected_num_get_work); |
| 238 EXPECT_EQ(expected_num_get_work, NumGetWork()); | |
| 239 } | 247 } |
| 240 } | 248 } |
| 241 | 249 |
| 242 } // namespace | 250 } // namespace |
| 243 } // namespace internal | 251 } // namespace internal |
| 244 } // namespace base | 252 } // namespace base |
| OLD | NEW |