Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(258)

Side by Side Diff: base/task_scheduler/scheduler_worker_thread_unittest.cc

Issue 1864333002: TaskScheduler: Delegate instead of callbacks for SchedulerWorkerThread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR gab #18 (add "The Task is still in |sequence| when this is called.") Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/task_scheduler/scheduler_worker_thread.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 class TaskSchedulerWorkerThreadTest : public testing::Test { 29 class TaskSchedulerWorkerThreadTest : public testing::Test,
30 public SchedulerWorkerThread::Delegate {
30 protected: 31 protected:
31 TaskSchedulerWorkerThreadTest() 32 TaskSchedulerWorkerThreadTest()
32 : num_main_entry_callback_cv_(lock_.CreateConditionVariable()), 33 : main_entry_called_(true, false),
33 num_get_work_callback_cv_(lock_.CreateConditionVariable()), 34 num_get_work_cv_(lock_.CreateConditionVariable()),
34 run_sequences_cv_(lock_.CreateConditionVariable()) {} 35 run_sequences_cv_(lock_.CreateConditionVariable()) {}
35 36
36 void SetUp() override { 37 void SetUp() override {
37 worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread( 38 worker_thread_ = SchedulerWorkerThread::CreateSchedulerWorkerThread(
38 ThreadPriority::NORMAL, 39 ThreadPriority::NORMAL, this, &task_tracker_);
39 Bind(&TaskSchedulerWorkerThreadTest::MainEntryCallback,
40 Unretained(this)),
41 Bind(&TaskSchedulerWorkerThreadTest::GetWorkCallback, Unretained(this)),
42 Bind(&TaskSchedulerWorkerThreadTest::RanTaskFromSequenceCallback,
43 Unretained(this)),
44 &task_tracker_);
45 ASSERT_TRUE(worker_thread_); 40 ASSERT_TRUE(worker_thread_);
46 WaitForNumMainEntryCallback(1); 41 main_entry_called_.Wait();
47 } 42 }
48 43
49 void TearDown() override { 44 void TearDown() override {
45 {
46 AutoSchedulerLock auto_lock(lock_);
47 EXPECT_FALSE(main_exit_called_);
48 }
49
50 worker_thread_->JoinForTesting(); 50 worker_thread_->JoinForTesting();
51 51
52 AutoSchedulerLock auto_lock(lock_); 52 AutoSchedulerLock auto_lock(lock_);
53 EXPECT_EQ(1U, num_main_entry_callback_); 53 EXPECT_TRUE(main_exit_called_);
54 } 54 }
55 55
56 // Wait until MainEntryCallback() has been called |num_main_entry_callback| 56 // Wait until GetWork() has been called |num_get_work| times.
57 // times. 57 void WaitForNumGetWork(size_t num_get_work) {
58 void WaitForNumMainEntryCallback(size_t num_main_entry_callback) {
59 AutoSchedulerLock auto_lock(lock_); 58 AutoSchedulerLock auto_lock(lock_);
60 while (num_main_entry_callback_ < num_main_entry_callback) 59 while (num_get_work_ < num_get_work)
61 num_main_entry_callback_cv_->Wait(); 60 num_get_work_cv_->Wait();
62 } 61 }
63 62
64 // Wait until GetWorkCallback() has been called |num_get_work_callback| times. 63 // Wait until there are no more Sequences to create and RanTaskFromSequence()
65 void WaitForNumGetWorkCallback(size_t num_get_work_callback) { 64 // has been invoked once for each Sequence returned by GetWork().
66 AutoSchedulerLock auto_lock(lock_);
67 while (num_get_work_callback_ < num_get_work_callback)
68 num_get_work_callback_cv_->Wait();
69 }
70
71 // Wait until there is no more Sequences to create and
72 // RanTaskFromSequenceCallback() has been invoked once for each Sequence
73 // returned by GetWorkCallback().
74 void WaitForAllSequencesToRun() { 65 void WaitForAllSequencesToRun() {
75 AutoSchedulerLock auto_lock(lock_); 66 AutoSchedulerLock auto_lock(lock_);
76 67
77 while (num_sequences_to_create_ > 0 || 68 while (num_sequences_to_create_ > 0 ||
78 run_sequences_.size() < created_sequences_.size()) { 69 run_sequences_.size() < created_sequences_.size()) {
79 run_sequences_cv_->Wait(); 70 run_sequences_cv_->Wait();
80 } 71 }
81 72
82 // Verify that RanTaskFromSequenceCallback() has been invoked with the 73 // Verify that RanTaskFromSequence() has been invoked with the same
83 // same Sequences that were returned by GetWorkCallback(). 74 // Sequences that were returned by GetWork().
84 EXPECT_EQ(created_sequences_, run_sequences_); 75 EXPECT_EQ(created_sequences_, run_sequences_);
85 76
86 // Verify that RunTaskCallback() has been invoked once for each Sequence 77 // Verify that RunTaskCallback() has been invoked once for each Sequence
87 // returned by GetWorkCallback(). 78 // returned by GetWork().
88 EXPECT_EQ(created_sequences_.size(), num_run_tasks_); 79 EXPECT_EQ(created_sequences_.size(), num_run_tasks_);
89 } 80 }
90 81
91 void SetNumSequencesToCreate(size_t num_sequences_to_create) { 82 void SetNumSequencesToCreate(size_t num_sequences_to_create) {
92 AutoSchedulerLock auto_lock(lock_); 83 AutoSchedulerLock auto_lock(lock_);
93 EXPECT_EQ(0U, num_sequences_to_create_); 84 EXPECT_EQ(0U, num_sequences_to_create_);
94 num_sequences_to_create_ = num_sequences_to_create; 85 num_sequences_to_create_ = num_sequences_to_create;
95 } 86 }
96 87
97 size_t NumGetWorkCallback() const { 88 size_t NumGetWork() const {
98 AutoSchedulerLock auto_lock(lock_); 89 AutoSchedulerLock auto_lock(lock_);
99 return num_get_work_callback_; 90 return num_get_work_;
100 } 91 }
101 92
102 std::unique_ptr<SchedulerWorkerThread> worker_thread_; 93 std::unique_ptr<SchedulerWorkerThread> worker_thread_;
103 94
104 private: 95 private:
105 void MainEntryCallback() { 96 // SchedulerWorkerThread::Delegate:
97 void OnMainEntry() override {
98 // Without this |auto_lock|, OnMainEntry() could be called twice without
99 // generating an error.
106 AutoSchedulerLock auto_lock(lock_); 100 AutoSchedulerLock auto_lock(lock_);
107 ++num_main_entry_callback_; 101 EXPECT_FALSE(main_entry_called_.IsSignaled());
108 num_main_entry_callback_cv_->Signal(); 102 main_entry_called_.Signal();
109 } 103 }
110 104
111 // Returns a Sequence that contains 1 Task if |num_sequences_to_create_| is 105 void OnMainExit() override {
112 // greater than 0. 106 AutoSchedulerLock auto_lock(lock_);
113 scoped_refptr<Sequence> GetWorkCallback( 107 EXPECT_FALSE(main_exit_called_);
114 SchedulerWorkerThread* worker_thread) { 108 main_exit_called_ = true;
109 }
110
111 scoped_refptr<Sequence> GetWork(
112 SchedulerWorkerThread* worker_thread) override {
115 EXPECT_EQ(worker_thread_.get(), worker_thread); 113 EXPECT_EQ(worker_thread_.get(), worker_thread);
116 114
117 { 115 {
118 AutoSchedulerLock auto_lock(lock_); 116 AutoSchedulerLock auto_lock(lock_);
119 117
120 // Increment the number of times that this callback has been invoked. 118 // Increment the number of times that this method has been called.
121 ++num_get_work_callback_; 119 ++num_get_work_;
122 num_get_work_callback_cv_->Signal(); 120 num_get_work_cv_->Signal();
123 121
124 // Check if a Sequence should be returned. 122 // Check if a Sequence should be returned.
125 if (num_sequences_to_create_ == 0) 123 if (num_sequences_to_create_ == 0)
126 return nullptr; 124 return nullptr;
127 --num_sequences_to_create_; 125 --num_sequences_to_create_;
128 } 126 }
129 127
130 // Create a Sequence that contains 1 Task. 128 // Create a Sequence that contains 1 Task.
131 scoped_refptr<Sequence> sequence(new Sequence); 129 scoped_refptr<Sequence> sequence(new Sequence);
132 task_tracker_.PostTask( 130 task_tracker_.PostTask(
133 Bind(IgnoreResult(&Sequence::PushTask), Unretained(sequence.get())), 131 Bind(IgnoreResult(&Sequence::PushTask), Unretained(sequence.get())),
134 WrapUnique(new Task( 132 WrapUnique(new Task(
135 FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback, 133 FROM_HERE, Bind(&TaskSchedulerWorkerThreadTest::RunTaskCallback,
136 Unretained(this)), 134 Unretained(this)),
137 TaskTraits()))); 135 TaskTraits())));
138 136
139 { 137 {
140 // Add the Sequence to the vector of created Sequences. 138 // Add the Sequence to the vector of created Sequences.
141 AutoSchedulerLock auto_lock(lock_); 139 AutoSchedulerLock auto_lock(lock_);
142 created_sequences_.push_back(sequence); 140 created_sequences_.push_back(sequence);
143 } 141 }
144 142
145 return sequence; 143 return sequence;
146 } 144 }
147 145
148 void RanTaskFromSequenceCallback(const SchedulerWorkerThread* worker_thread, 146 void RanTaskFromSequence(scoped_refptr<Sequence> sequence) override {
149 scoped_refptr<Sequence> sequence) {
150 EXPECT_EQ(worker_thread_.get(), worker_thread);
151
152 AutoSchedulerLock auto_lock(lock_); 147 AutoSchedulerLock auto_lock(lock_);
153 run_sequences_.push_back(std::move(sequence)); 148 run_sequences_.push_back(std::move(sequence));
154 run_sequences_cv_->Signal(); 149 run_sequences_cv_->Signal();
155 } 150 }
156 151
157 void RunTaskCallback() { 152 void RunTaskCallback() {
158 AutoSchedulerLock auto_lock(lock_); 153 AutoSchedulerLock auto_lock(lock_);
159 ++num_run_tasks_; 154 ++num_run_tasks_;
160 } 155 }
161 156
162 TaskTracker task_tracker_; 157 TaskTracker task_tracker_;
163 158
164 // Synchronizes access to all members below. 159 // Synchronizes access to all members below.
165 mutable SchedulerLock lock_; 160 mutable SchedulerLock lock_;
166 161
167 // Number of times that MainEntryCallback() has been called. 162 // Signaled once OnMainEntry() has been called.
168 size_t num_main_entry_callback_ = 0; 163 WaitableEvent main_entry_called_;
169 164
170 // Condition variable signaled when |num_main_entry_callback_| is incremented. 165 // True once OnMainExit() has been called.
171 std::unique_ptr<ConditionVariable> num_main_entry_callback_cv_; 166 bool main_exit_called_ = false;
172 167
173 // Number of Sequences that should be created by GetWorkCallback(). When this 168 // Number of Sequences that should be created by GetWork(). When this
174 // is 0, GetWorkCallback() returns nullptr. 169 // is 0, GetWork() returns nullptr.
175 size_t num_sequences_to_create_ = 0; 170 size_t num_sequences_to_create_ = 0;
176 171
177 // Number of times that GetWorkCallback() has been called. 172 // Number of times that GetWork() has been called.
178 size_t num_get_work_callback_ = 0; 173 size_t num_get_work_ = 0;
179 174
180 // Condition variable signaled when |num_get_work_callback_| is incremented. 175 // Condition variable signaled when |num_get_work_| is incremented.
181 std::unique_ptr<ConditionVariable> num_get_work_callback_cv_; 176 std::unique_ptr<ConditionVariable> num_get_work_cv_;
182 177
183 // Sequences created by GetWorkCallback(). 178 // Sequences created by GetWork().
184 std::vector<scoped_refptr<Sequence>> created_sequences_; 179 std::vector<scoped_refptr<Sequence>> created_sequences_;
185 180
186 // Sequences passed to RanTaskFromSequenceCallback(). 181 // Sequences passed to RanTaskFromSequence().
187 std::vector<scoped_refptr<Sequence>> run_sequences_; 182 std::vector<scoped_refptr<Sequence>> run_sequences_;
188 183
189 // Condition variable signaled when a Sequence is added to |run_sequences_|. 184 // Condition variable signaled when a Sequence is added to |run_sequences_|.
190 std::unique_ptr<ConditionVariable> run_sequences_cv_; 185 std::unique_ptr<ConditionVariable> run_sequences_cv_;
191 186
192 // Number of times that RunTaskCallback() has been called. 187 // Number of times that RunTaskCallback() has been called.
193 size_t num_run_tasks_ = 0; 188 size_t num_run_tasks_ = 0;
194 189
195 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadTest); 190 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerThreadTest);
196 }; 191 };
197 192
198 // Verify that when GetWorkCallback() continuously returns Sequences, all Tasks 193 // Verify that when GetWork() continuously returns Sequences, all Tasks in these
199 // in these Sequences run successfully. The SchedulerWorkerThread is woken up 194 // Sequences run successfully. The SchedulerWorkerThread is woken up once.
200 // once.
201 TEST_F(TaskSchedulerWorkerThreadTest, ContinousWork) { 195 TEST_F(TaskSchedulerWorkerThreadTest, ContinousWork) {
202 // Set GetWorkCallback() to return |kNumSequencesPerTest| Sequences before 196 // Set GetWork() to return |kNumSequencesPerTest| Sequences before starting to
203 // starting to return nullptr. 197 // return nullptr.
204 SetNumSequencesToCreate(kNumSequencesPerTest); 198 SetNumSequencesToCreate(kNumSequencesPerTest);
205 199
206 // Wake up |worker_thread_| and wait until it has run all the Tasks returned 200 // Wake up |worker_thread_| and wait until it has run all the Tasks returned
207 // by GetWorkCallback(). 201 // by GetWork().
208 worker_thread_->WakeUp(); 202 worker_thread_->WakeUp();
209 WaitForAllSequencesToRun(); 203 WaitForAllSequencesToRun();
210 204
211 // Expect |kNumSequencesPerTest| calls to GetWorkCallback() in which it 205 // Expect |kNumSequencesPerTest| calls to GetWork() in which it returned a
212 // returned a Sequence and 1 call in which it returned nullptr. 206 // Sequence and 1 call in which it returned nullptr.
213 const size_t expected_num_get_work_callback = kNumSequencesPerTest + 1; 207 const size_t expected_num_get_work = kNumSequencesPerTest + 1;
214 WaitForNumGetWorkCallback(expected_num_get_work_callback); 208 WaitForNumGetWork(expected_num_get_work);
215 EXPECT_EQ(expected_num_get_work_callback, NumGetWorkCallback()); 209 EXPECT_EQ(expected_num_get_work, NumGetWork());
216 } 210 }
217 211
218 // Verify that when GetWorkCallback() alternates between returning a Sequence 212 // Verify that when GetWork() alternates between returning a Sequence and
219 // and returning nullptr, all Tasks in the returned Sequences run successfully. 213 // returning nullptr, all Tasks in the returned Sequences run successfully. The
220 // The SchedulerWorkerThread is woken up once for each Sequence. 214 // SchedulerWorkerThread is woken up once for each Sequence.
221 TEST_F(TaskSchedulerWorkerThreadTest, IntermittentWork) { 215 TEST_F(TaskSchedulerWorkerThreadTest, IntermittentWork) {
222 for (size_t i = 0; i < kNumSequencesPerTest; ++i) { 216 for (size_t i = 0; i < kNumSequencesPerTest; ++i) {
223 // Set GetWorkCallback() to return 1 Sequence before starting to return 217 // Set GetWork() to return 1 Sequence before starting to return
224 // nullptr. 218 // nullptr.
225 SetNumSequencesToCreate(1); 219 SetNumSequencesToCreate(1);
226 220
227 // 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 the Task returned by
228 // by GetWorkCallback(). 222 // GetWork().
229 worker_thread_->WakeUp(); 223 worker_thread_->WakeUp();
230 WaitForAllSequencesToRun(); 224 WaitForAllSequencesToRun();
231 225
232 // Expect |i| calls to GetWorkCallback() in which it returned a Sequence and 226 // Expect |i| calls to GetWork() in which it returned a Sequence and
233 // |i| calls in which it returned nullptr. 227 // |i| calls in which it returned nullptr.
234 const size_t expected_num_get_work_callback = 2 * (i + 1); 228 const size_t expected_num_get_work = 2 * (i + 1);
235 WaitForNumGetWorkCallback(expected_num_get_work_callback); 229 WaitForNumGetWork(expected_num_get_work);
236 EXPECT_EQ(expected_num_get_work_callback, NumGetWorkCallback()); 230 EXPECT_EQ(expected_num_get_work, NumGetWork());
237 } 231 }
238 } 232 }
239 233
240 } // namespace 234 } // namespace
241 } // namespace internal 235 } // namespace internal
242 } // namespace base 236 } // namespace base
OLDNEW
« no previous file with comments | « base/task_scheduler/scheduler_worker_thread.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698