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> |
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/synchronization/condition_variable.h" | 16 #include "base/synchronization/condition_variable.h" |
17 #include "base/task_scheduler/scheduler_lock.h" | 17 #include "base/task_scheduler/scheduler_lock.h" |
18 #include "base/task_scheduler/sequence.h" | 18 #include "base/task_scheduler/sequence.h" |
19 #include "base/task_scheduler/task.h" | 19 #include "base/task_scheduler/task.h" |
20 #include "base/task_scheduler/task_tracker.h" | 20 #include "base/task_scheduler/task_tracker.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
22 | 22 |
23 namespace base { | 23 namespace base { |
24 namespace internal { | 24 namespace internal { |
25 namespace { | 25 namespace { |
26 | 26 |
27 const size_t kNumSequencesPerTest = 150; | 27 const size_t kNumSequencesPerTest = 150; |
28 | 28 |
29 // The test parameter is the number of Tasks per Sequence returned by GetWork(). | 29 // The test parameter is the number of Tasks per Sequence returned by GetWork(). |
30 class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t>, | 30 class TaskSchedulerWorkerThreadTest : public testing::TestWithParam<size_t> { |
31 public SchedulerWorkerThread::Delegate { | |
32 protected: | 31 protected: |
33 TaskSchedulerWorkerThreadTest() | 32 TaskSchedulerWorkerThreadTest() |
34 : main_entry_called_(true, false), | 33 : main_entry_called_(true, false), |
35 num_get_work_cv_(lock_.CreateConditionVariable()) {} | 34 num_get_work_cv_(lock_.CreateConditionVariable()) {} |
36 | 35 |
37 void SetUp() override { | 36 void SetUp() override { |
38 worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread( | 37 worker_thread_ = SchedulerWorkerThread::CreateWorkerThread( |
39 ThreadPriority::NORMAL, this, &task_tracker_); | 38 ThreadPriority::NORMAL, |
39 WrapUnique(new SchedulerWorkerThreadDelegateImpl(this)), | |
gab
2016/04/22 19:30:29
This compiles without a fwd-decl of SchedulerWorke
fdoray
2016/04/22 22:46:46
Yes. We can use any type defined in the class in t
| |
40 &task_tracker_); | |
40 ASSERT_TRUE(worker_thread_); | 41 ASSERT_TRUE(worker_thread_); |
41 main_entry_called_.Wait(); | 42 main_entry_called_.Wait(); |
42 } | 43 } |
43 | 44 |
44 void TearDown() override { | 45 void TearDown() override { |
45 worker_thread_->JoinForTesting(); | 46 worker_thread_->JoinForTesting(); |
46 } | 47 } |
47 | 48 |
48 size_t TasksPerSequence() const { return GetParam(); } | 49 size_t TasksPerSequence() const { return GetParam(); } |
49 | 50 |
(...skipping 26 matching lines...) Expand all Loading... | |
76 } | 77 } |
77 | 78 |
78 std::vector<scoped_refptr<Sequence>> EnqueuedSequences() { | 79 std::vector<scoped_refptr<Sequence>> EnqueuedSequences() { |
79 AutoSchedulerLock auto_lock(lock_); | 80 AutoSchedulerLock auto_lock(lock_); |
80 return enqueued_sequences_; | 81 return enqueued_sequences_; |
81 } | 82 } |
82 | 83 |
83 std::unique_ptr<SchedulerWorkerThread> worker_thread_; | 84 std::unique_ptr<SchedulerWorkerThread> worker_thread_; |
84 | 85 |
85 private: | 86 private: |
86 // SchedulerWorkerThread::Delegate: | 87 class SchedulerWorkerThreadDelegateImpl |
gab
2016/04/22 19:30:29
Name this differently than main impl, e.g. Schedul
danakj
2016/04/22 20:16:33
nit: not a fan of "test" in class names. Suggest f
robliao
2016/04/22 20:30:48
There is a reasonable precedent in Chrome to name
fdoray
2016/04/22 22:46:46
Done. Renamed to TestSchedulerWorkerThreadDelegate
| |
87 void OnMainEntry() override { | 88 : public SchedulerWorkerThread::Delegate { |
88 // Without this |auto_lock|, OnMainEntry() could be called twice without | 89 public: |
89 // generating an error. | 90 SchedulerWorkerThreadDelegateImpl(TaskSchedulerWorkerThreadTest* outer) |
90 AutoSchedulerLock auto_lock(lock_); | 91 : outer_(outer) {} |
91 EXPECT_FALSE(main_entry_called_.IsSignaled()); | |
92 main_entry_called_.Signal(); | |
93 } | |
94 | 92 |
95 scoped_refptr<Sequence> GetWork( | 93 // SchedulerWorkerThread::Delegate: |
96 SchedulerWorkerThread* worker_thread) override { | 94 void OnMainEntry() override { |
97 EXPECT_EQ(worker_thread_.get(), worker_thread); | 95 // Without this |auto_lock|, OnMainEntry() could be called twice without |
robliao
2016/04/22 20:30:48
Nit: Without synchronization
fdoray
2016/04/22 22:46:46
Done.
| |
98 | 96 // generating an error. |
99 { | 97 AutoSchedulerLock auto_lock(outer_->lock_); |
100 AutoSchedulerLock auto_lock(lock_); | 98 EXPECT_FALSE(outer_->main_entry_called_.IsSignaled()); |
101 | 99 outer_->main_entry_called_.Signal(); |
102 // Increment the number of times that this method has been called. | |
103 ++num_get_work_; | |
104 num_get_work_cv_->Signal(); | |
105 | |
106 // Verify that this method isn't called more times than expected. | |
107 EXPECT_LE(num_get_work_, max_get_work_); | |
108 | |
109 // Check if a Sequence should be returned. | |
110 if (num_sequences_to_create_ == 0) | |
111 return nullptr; | |
112 --num_sequences_to_create_; | |
113 } | 100 } |
114 | 101 |
115 // Create a Sequence with TasksPerSequence() Tasks. | 102 scoped_refptr<Sequence> GetWork( |
116 scoped_refptr<Sequence> sequence(new Sequence); | 103 SchedulerWorkerThread* worker_thread) override { |
117 for (size_t i = 0; i < TasksPerSequence(); ++i) { | 104 EXPECT_EQ(outer_->worker_thread_.get(), worker_thread); |
118 std::unique_ptr<Task> task(new Task( | 105 |
119 FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback, | 106 { |
120 Unretained(this)), | 107 AutoSchedulerLock auto_lock(outer_->lock_); |
121 TaskTraits(), TimeTicks())); | 108 |
122 EXPECT_TRUE(task_tracker_.WillPostTask(task.get())); | 109 // Increment the number of times that this method has been called. |
123 sequence->PushTask(std::move(task)); | 110 ++outer_->num_get_work_; |
111 outer_->num_get_work_cv_->Signal(); | |
112 | |
113 // Verify that this method isn't called more times than expected. | |
114 EXPECT_LE(outer_->num_get_work_, outer_->max_get_work_); | |
115 | |
116 // Check if a Sequence should be returned. | |
117 if (outer_->num_sequences_to_create_ == 0) | |
118 return nullptr; | |
119 --outer_->num_sequences_to_create_; | |
120 } | |
121 | |
122 // Create a Sequence with TasksPerSequence() Tasks. | |
123 scoped_refptr<Sequence> sequence(new Sequence); | |
124 for (size_t i = 0; i < outer_->TasksPerSequence(); ++i) { | |
125 std::unique_ptr<Task> task(new Task( | |
126 FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback, | |
127 Unretained(outer_)), | |
128 TaskTraits(), TimeTicks())); | |
129 EXPECT_TRUE(outer_->task_tracker_.WillPostTask(task.get())); | |
130 sequence->PushTask(std::move(task)); | |
131 } | |
132 | |
133 { | |
134 // Add the Sequence to the vector of created Sequences. | |
135 AutoSchedulerLock auto_lock(outer_->lock_); | |
136 outer_->created_sequences_.push_back(sequence); | |
137 } | |
138 | |
139 return sequence; | |
124 } | 140 } |
125 | 141 |
126 { | 142 // This override verifies that |sequence| contains the expected number of |
127 // Add the Sequence to the vector of created Sequences. | 143 // Tasks and adds it to |enqueued_sequences_|. Unlike a normal |
128 AutoSchedulerLock auto_lock(lock_); | 144 // EnqueueSequence |
129 created_sequences_.push_back(sequence); | 145 // implementation, it doesn't reinsert |sequence| into a queue for further |
146 // execution. | |
147 void EnqueueSequence(scoped_refptr<Sequence> sequence) override { | |
148 EXPECT_GT(outer_->TasksPerSequence(), 1U); | |
149 | |
150 // Verify that |sequence| contains TasksPerSequence() - 1 Tasks. | |
151 for (size_t i = 0; i < outer_->TasksPerSequence() - 1; ++i) { | |
152 EXPECT_TRUE(sequence->PeekTask()); | |
153 sequence->PopTask(); | |
154 } | |
155 EXPECT_FALSE(sequence->PeekTask()); | |
156 | |
157 // Add |sequence| to |enqueued_sequences_|. | |
158 AutoSchedulerLock auto_lock(outer_->lock_); | |
159 outer_->enqueued_sequences_.push_back(std::move(sequence)); | |
160 EXPECT_LE(outer_->enqueued_sequences_.size(), | |
161 outer_->created_sequences_.size()); | |
130 } | 162 } |
131 | 163 |
132 return sequence; | 164 private: |
133 } | 165 TaskSchedulerWorkerThreadTest* outer_; |
134 | 166 }; |
135 // This override verifies that |sequence| contains the expected number of | |
136 // Tasks and adds it to |enqueued_sequences_|. Unlike a normal EnqueueSequence | |
137 // implementation, it doesn't reinsert |sequence| into a queue for further | |
138 // execution. | |
139 void EnqueueSequence(scoped_refptr<Sequence> sequence) override { | |
140 EXPECT_GT(TasksPerSequence(), 1U); | |
141 | |
142 // Verify that |sequence| contains TasksPerSequence() - 1 Tasks. | |
143 for (size_t i = 0; i < TasksPerSequence() - 1; ++i) { | |
144 EXPECT_TRUE(sequence->PeekTask()); | |
145 sequence->PopTask(); | |
146 } | |
147 EXPECT_FALSE(sequence->PeekTask()); | |
148 | |
149 // Add |sequence| to |enqueued_sequences_|. | |
150 AutoSchedulerLock auto_lock(lock_); | |
151 enqueued_sequences_.push_back(std::move(sequence)); | |
152 EXPECT_LE(enqueued_sequences_.size(), created_sequences_.size()); | |
153 } | |
154 | 167 |
155 void RunTaskCallback() { | 168 void RunTaskCallback() { |
156 AutoSchedulerLock auto_lock(lock_); | 169 AutoSchedulerLock auto_lock(lock_); |
157 ++num_run_tasks_; | 170 ++num_run_tasks_; |
158 EXPECT_LE(num_run_tasks_, created_sequences_.size()); | 171 EXPECT_LE(num_run_tasks_, created_sequences_.size()); |
159 } | 172 } |
160 | 173 |
161 TaskTracker task_tracker_; | 174 TaskTracker task_tracker_; |
162 | 175 |
163 // Synchronizes access to all members below. | 176 // Synchronizes access to all members below. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
255 INSTANTIATE_TEST_CASE_P(OneTaskPerSequence, | 268 INSTANTIATE_TEST_CASE_P(OneTaskPerSequence, |
256 TaskSchedulerWorkerThreadTest, | 269 TaskSchedulerWorkerThreadTest, |
257 ::testing::Values(1)); | 270 ::testing::Values(1)); |
258 INSTANTIATE_TEST_CASE_P(TwoTasksPerSequence, | 271 INSTANTIATE_TEST_CASE_P(TwoTasksPerSequence, |
259 TaskSchedulerWorkerThreadTest, | 272 TaskSchedulerWorkerThreadTest, |
260 ::testing::Values(2)); | 273 ::testing::Values(2)); |
261 | 274 |
262 } // namespace | 275 } // namespace |
263 } // namespace internal | 276 } // namespace internal |
264 } // namespace base | 277 } // namespace base |
OLD | NEW |