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/task_tracker.h" | 5 #include "base/task_scheduler/task_tracker.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <vector> | |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/logging.h" | 11 #include "base/logging.h" |
11 #include "base/macros.h" | 12 #include "base/macros.h" |
12 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
13 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
14 #include "base/sequenced_task_runner.h" | 15 #include "base/sequenced_task_runner.h" |
15 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
16 #include "base/synchronization/waitable_event.h" | 17 #include "base/synchronization/waitable_event.h" |
18 #include "base/task_scheduler/scheduler_lock.h" | |
17 #include "base/task_scheduler/task.h" | 19 #include "base/task_scheduler/task.h" |
18 #include "base/task_scheduler/task_traits.h" | 20 #include "base/task_scheduler/task_traits.h" |
19 #include "base/task_scheduler/test_utils.h" | 21 #include "base/task_scheduler/test_utils.h" |
20 #include "base/test/test_simple_task_runner.h" | 22 #include "base/test/test_simple_task_runner.h" |
21 #include "base/threading/platform_thread.h" | 23 #include "base/threading/platform_thread.h" |
22 #include "base/threading/sequenced_task_runner_handle.h" | 24 #include "base/threading/sequenced_task_runner_handle.h" |
23 #include "base/threading/simple_thread.h" | 25 #include "base/threading/simple_thread.h" |
24 #include "base/threading/thread_restrictions.h" | 26 #include "base/threading/thread_restrictions.h" |
25 #include "base/threading/thread_task_runner_handle.h" | 27 #include "base/threading/thread_task_runner_handle.h" |
26 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
27 | 29 |
28 namespace base { | 30 namespace base { |
29 namespace internal { | 31 namespace internal { |
30 | 32 |
31 namespace { | 33 namespace { |
32 | 34 |
35 constexpr size_t kLoadTestNumIterations = 100; | |
36 | |
33 // Calls TaskTracker::Shutdown() asynchronously. | 37 // Calls TaskTracker::Shutdown() asynchronously. |
34 class ThreadCallingShutdown : public SimpleThread { | 38 class ThreadCallingShutdown : public SimpleThread { |
35 public: | 39 public: |
36 explicit ThreadCallingShutdown(TaskTracker* tracker) | 40 explicit ThreadCallingShutdown(TaskTracker* tracker) |
37 : SimpleThread("ThreadCallingShutdown"), | 41 : SimpleThread("ThreadCallingShutdown"), |
38 tracker_(tracker), | 42 tracker_(tracker), |
39 has_returned_(WaitableEvent::ResetPolicy::MANUAL, | 43 has_returned_(WaitableEvent::ResetPolicy::MANUAL, |
40 WaitableEvent::InitialState::NOT_SIGNALED) {} | 44 WaitableEvent::InitialState::NOT_SIGNALED) {} |
41 | 45 |
42 // Returns true once the async call to Shutdown() has returned. | 46 // Returns true once the async call to Shutdown() has returned. |
43 bool has_returned() { return has_returned_.IsSignaled(); } | 47 bool has_returned() { return has_returned_.IsSignaled(); } |
44 | 48 |
45 private: | 49 private: |
46 void Run() override { | 50 void Run() override { |
47 tracker_->Shutdown(); | 51 tracker_->Shutdown(); |
48 has_returned_.Signal(); | 52 has_returned_.Signal(); |
49 } | 53 } |
50 | 54 |
51 TaskTracker* const tracker_; | 55 TaskTracker* const tracker_; |
52 WaitableEvent has_returned_; | 56 WaitableEvent has_returned_; |
53 | 57 |
54 DISALLOW_COPY_AND_ASSIGN(ThreadCallingShutdown); | 58 DISALLOW_COPY_AND_ASSIGN(ThreadCallingShutdown); |
55 }; | 59 }; |
56 | 60 |
57 // Runs a task asynchronously. | 61 class ThreadPostingAndRunningTask : public SimpleThread { |
58 class ThreadRunningTask : public SimpleThread { | |
59 public: | 62 public: |
60 ThreadRunningTask(TaskTracker* tracker, const Task* task) | 63 enum Action { |
robliao
2016/06/20 21:32:20
Nit: enum class.
fdoray
2016/06/29 18:22:37
Done.
| |
61 : SimpleThread("ThreadRunningTask"), tracker_(tracker), task_(task) {} | 64 WILL_POST = 0x1, |
65 RUN = 0x2, | |
66 WILL_POST_AND_RUN = WILL_POST | RUN, | |
67 }; | |
68 | |
69 ThreadPostingAndRunningTask(TaskTracker* tracker, | |
70 const Task* task, | |
71 Action action, | |
72 bool expect_post_succeeds) | |
73 : SimpleThread("ThreadPostingAndRunningTask"), | |
74 tracker_(tracker), | |
75 task_(task), | |
76 action_(action), | |
77 expect_post_succeeds_(expect_post_succeeds) {} | |
62 | 78 |
63 private: | 79 private: |
64 void Run() override { tracker_->RunTask(task_); } | 80 void Run() override { |
81 bool post_succeeded = true; | |
82 if (action_ & WILL_POST) { | |
83 post_succeeded = tracker_->WillPostTask(task_); | |
84 EXPECT_EQ(expect_post_succeeds_, post_succeeded); | |
85 } | |
86 if (post_succeeded && action_ & RUN) | |
87 tracker_->RunTask(task_); | |
88 } | |
65 | 89 |
66 TaskTracker* const tracker_; | 90 TaskTracker* const tracker_; |
67 const Task* const task_; | 91 const Task* const task_; |
92 const Action action_; | |
93 const bool expect_post_succeeds_; | |
68 | 94 |
69 DISALLOW_COPY_AND_ASSIGN(ThreadRunningTask); | 95 DISALLOW_COPY_AND_ASSIGN(ThreadPostingAndRunningTask); |
70 }; | 96 }; |
71 | 97 |
72 class ScopedSetSingletonAllowed { | 98 class ScopedSetSingletonAllowed { |
73 public: | 99 public: |
74 ScopedSetSingletonAllowed(bool singleton_allowed) | 100 ScopedSetSingletonAllowed(bool singleton_allowed) |
75 : previous_value_( | 101 : previous_value_( |
76 ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {} | 102 ThreadRestrictions::SetSingletonAllowed(singleton_allowed)) {} |
77 ~ScopedSetSingletonAllowed() { | 103 ~ScopedSetSingletonAllowed() { |
78 ThreadRestrictions::SetSingletonAllowed(previous_value_); | 104 ThreadRestrictions::SetSingletonAllowed(previous_value_); |
79 } | 105 } |
(...skipping 16 matching lines...) Expand all Loading... | |
96 } | 122 } |
97 | 123 |
98 // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown() | 124 // Calls tracker_->Shutdown() on a new thread. When this returns, Shutdown() |
99 // method has been entered on the new thread, but it hasn't necessarily | 125 // method has been entered on the new thread, but it hasn't necessarily |
100 // returned. | 126 // returned. |
101 void CallShutdownAsync() { | 127 void CallShutdownAsync() { |
102 ASSERT_FALSE(thread_calling_shutdown_); | 128 ASSERT_FALSE(thread_calling_shutdown_); |
103 thread_calling_shutdown_.reset(new ThreadCallingShutdown(&tracker_)); | 129 thread_calling_shutdown_.reset(new ThreadCallingShutdown(&tracker_)); |
104 thread_calling_shutdown_->Start(); | 130 thread_calling_shutdown_->Start(); |
105 while (!tracker_.IsShuttingDownForTesting() && | 131 while (!tracker_.IsShuttingDownForTesting() && |
106 !tracker_.shutdown_completed()) { | 132 !tracker_.ShutdownCompleted()) { |
107 PlatformThread::YieldCurrentThread(); | 133 PlatformThread::YieldCurrentThread(); |
108 } | 134 } |
109 } | 135 } |
110 | 136 |
111 void WaitForAsyncShutdownCompleted() { | 137 void WaitForAsyncShutdownCompleted() { |
112 ASSERT_TRUE(thread_calling_shutdown_); | 138 ASSERT_TRUE(thread_calling_shutdown_); |
113 thread_calling_shutdown_->Join(); | 139 thread_calling_shutdown_->Join(); |
114 EXPECT_TRUE(thread_calling_shutdown_->has_returned()); | 140 EXPECT_TRUE(thread_calling_shutdown_->has_returned()); |
115 EXPECT_TRUE(tracker_.shutdown_completed()); | 141 EXPECT_TRUE(tracker_.ShutdownCompleted()); |
116 } | 142 } |
117 | 143 |
118 void VerifyAsyncShutdownInProgress() { | 144 void VerifyAsyncShutdownInProgress() { |
119 ASSERT_TRUE(thread_calling_shutdown_); | 145 ASSERT_TRUE(thread_calling_shutdown_); |
120 EXPECT_FALSE(thread_calling_shutdown_->has_returned()); | 146 EXPECT_FALSE(thread_calling_shutdown_->has_returned()); |
121 EXPECT_FALSE(tracker_.shutdown_completed()); | 147 EXPECT_FALSE(tracker_.ShutdownCompleted()); |
122 EXPECT_TRUE(tracker_.IsShuttingDownForTesting()); | 148 EXPECT_TRUE(tracker_.IsShuttingDownForTesting()); |
123 } | 149 } |
124 | 150 |
151 size_t NumTasksExecuted() { | |
152 AutoSchedulerLock auto_lock(lock_); | |
153 return num_tasks_executed_; | |
154 } | |
155 | |
125 TaskTracker tracker_; | 156 TaskTracker tracker_; |
126 size_t num_tasks_executed_ = 0; | |
127 | 157 |
128 private: | 158 private: |
129 void RunTaskCallback() { ++num_tasks_executed_; } | 159 void RunTaskCallback() { |
160 AutoSchedulerLock auto_lock(lock_); | |
161 ++num_tasks_executed_; | |
162 } | |
130 | 163 |
131 std::unique_ptr<ThreadCallingShutdown> thread_calling_shutdown_; | 164 std::unique_ptr<ThreadCallingShutdown> thread_calling_shutdown_; |
132 | 165 |
166 // Synchronizes accesses to |num_tasks_executed_|. | |
167 SchedulerLock lock_; | |
168 | |
169 size_t num_tasks_executed_ = 0; | |
170 | |
133 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest); | 171 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest); |
134 }; | 172 }; |
135 | 173 |
136 #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \ | 174 #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \ |
137 do { \ | 175 do { \ |
138 SCOPED_TRACE(""); \ | 176 SCOPED_TRACE(""); \ |
139 WaitForAsyncShutdownCompleted(); \ | 177 WaitForAsyncShutdownCompleted(); \ |
140 } while (false) | 178 } while (false) |
141 | 179 |
142 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \ | 180 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \ |
143 do { \ | 181 do { \ |
144 SCOPED_TRACE(""); \ | 182 SCOPED_TRACE(""); \ |
145 VerifyAsyncShutdownInProgress(); \ | 183 VerifyAsyncShutdownInProgress(); \ |
146 } while (false) | 184 } while (false) |
147 | 185 |
148 } // namespace | 186 } // namespace |
149 | 187 |
150 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) { | 188 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) { |
151 std::unique_ptr<Task> task(CreateTask(GetParam())); | 189 std::unique_ptr<Task> task(CreateTask(GetParam())); |
152 | 190 |
153 // Inform |task_tracker_| that |task| will be posted. | 191 // Inform |task_tracker_| that |task| will be posted. |
154 EXPECT_TRUE(tracker_.WillPostTask(task.get())); | 192 EXPECT_TRUE(tracker_.WillPostTask(task.get())); |
155 | 193 |
156 // Run the task. | 194 // Run the task. |
157 EXPECT_EQ(0U, num_tasks_executed_); | 195 EXPECT_EQ(0U, NumTasksExecuted()); |
158 tracker_.RunTask(task.get()); | 196 tracker_.RunTask(task.get()); |
159 EXPECT_EQ(1U, num_tasks_executed_); | 197 EXPECT_EQ(1U, NumTasksExecuted()); |
160 | 198 |
161 // Shutdown() shouldn't block. | 199 // Shutdown() shouldn't block. |
162 tracker_.Shutdown(); | 200 tracker_.Shutdown(); |
163 } | 201 } |
164 | 202 |
165 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) { | 203 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) { |
166 // Create a task that will block until |event| is signaled. | 204 // Create a task that will block until |event| is signaled. |
167 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC, | 205 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC, |
168 WaitableEvent::InitialState::NOT_SIGNALED); | 206 WaitableEvent::InitialState::NOT_SIGNALED); |
169 std::unique_ptr<Task> blocked_task( | 207 std::unique_ptr<Task> blocked_task( |
170 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)), | 208 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)), |
171 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); | 209 TaskTraits().WithShutdownBehavior(GetParam()), TimeDelta())); |
172 | 210 |
173 // Inform |task_tracker_| that |blocked_task| will be posted. | 211 // Inform |task_tracker_| that |blocked_task| will be posted. |
174 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get())); | 212 EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get())); |
175 | 213 |
176 // Run the task asynchronouly. | 214 // Run the task asynchronouly. |
177 ThreadRunningTask thread_running_task(&tracker_, blocked_task.get()); | 215 ThreadPostingAndRunningTask thread_running_task( |
216 &tracker_, blocked_task.get(), ThreadPostingAndRunningTask::RUN, false); | |
178 thread_running_task.Start(); | 217 thread_running_task.Start(); |
179 | 218 |
180 // Initiate shutdown while the task is running. | 219 // Initiate shutdown while the task is running. |
181 CallShutdownAsync(); | 220 CallShutdownAsync(); |
182 | 221 |
183 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { | 222 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { |
184 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. | 223 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. |
185 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 224 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
186 } else { | 225 } else { |
187 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. | 226 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. |
(...skipping 19 matching lines...) Expand all Loading... | |
207 std::unique_ptr<Task> block_shutdown_task( | 246 std::unique_ptr<Task> block_shutdown_task( |
208 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 247 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
209 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); | 248 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); |
210 | 249 |
211 // Call Shutdown() asynchronously. | 250 // Call Shutdown() asynchronously. |
212 CallShutdownAsync(); | 251 CallShutdownAsync(); |
213 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 252 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
214 | 253 |
215 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it | 254 // Try to run |task|. It should only run it it's BLOCK_SHUTDOWN. Otherwise it |
216 // should be discarded. | 255 // should be discarded. |
217 EXPECT_EQ(0U, num_tasks_executed_); | 256 EXPECT_EQ(0U, NumTasksExecuted()); |
218 tracker_.RunTask(task.get()); | 257 tracker_.RunTask(task.get()); |
219 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 1U : 0U, | 258 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 1U : 0U, |
220 num_tasks_executed_); | 259 NumTasksExecuted()); |
221 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 260 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
222 | 261 |
223 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. | 262 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. |
224 tracker_.RunTask(block_shutdown_task.get()); | 263 tracker_.RunTask(block_shutdown_task.get()); |
225 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, | 264 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, |
226 num_tasks_executed_); | 265 NumTasksExecuted()); |
227 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 266 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
228 } | 267 } |
229 | 268 |
230 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) { | 269 TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) { |
231 // Inform |task_tracker_| that a task will be posted. | 270 // Inform |task_tracker_| that a task will be posted. |
232 std::unique_ptr<Task> task(CreateTask(GetParam())); | 271 std::unique_ptr<Task> task(CreateTask(GetParam())); |
233 EXPECT_TRUE(tracker_.WillPostTask(task.get())); | 272 EXPECT_TRUE(tracker_.WillPostTask(task.get())); |
234 | 273 |
235 // Call Shutdown() asynchronously. | 274 // Call Shutdown() asynchronously. |
236 CallShutdownAsync(); | 275 CallShutdownAsync(); |
237 EXPECT_EQ(0U, num_tasks_executed_); | 276 EXPECT_EQ(0U, NumTasksExecuted()); |
238 | 277 |
239 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { | 278 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { |
240 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 279 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
241 | 280 |
242 // Run the task to unblock shutdown. | 281 // Run the task to unblock shutdown. |
243 tracker_.RunTask(task.get()); | 282 tracker_.RunTask(task.get()); |
244 EXPECT_EQ(1U, num_tasks_executed_); | 283 EXPECT_EQ(1U, NumTasksExecuted()); |
245 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 284 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
246 | 285 |
247 // It is not possible to test running a BLOCK_SHUTDOWN task posted before | 286 // It is not possible to test running a BLOCK_SHUTDOWN task posted before |
248 // shutdown after shutdown because Shutdown() won't return if there are | 287 // shutdown after shutdown because Shutdown() won't return if there are |
249 // pending BLOCK_SHUTDOWN tasks. | 288 // pending BLOCK_SHUTDOWN tasks. |
250 } else { | 289 } else { |
251 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 290 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
252 | 291 |
253 // The task shouldn't be allowed to run after shutdown. | 292 // The task shouldn't be allowed to run after shutdown. |
254 tracker_.RunTask(task.get()); | 293 tracker_.RunTask(task.get()); |
255 EXPECT_EQ(0U, num_tasks_executed_); | 294 EXPECT_EQ(0U, NumTasksExecuted()); |
256 } | 295 } |
257 } | 296 } |
258 | 297 |
259 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) { | 298 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) { |
260 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to | 299 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to |
261 // block shutdown. | 300 // block shutdown. |
262 std::unique_ptr<Task> block_shutdown_task( | 301 std::unique_ptr<Task> block_shutdown_task( |
263 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 302 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
264 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); | 303 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); |
265 | 304 |
266 // Call Shutdown() asynchronously. | 305 // Call Shutdown() asynchronously. |
267 CallShutdownAsync(); | 306 CallShutdownAsync(); |
268 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 307 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
269 | 308 |
270 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { | 309 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { |
271 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. | 310 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. |
272 std::unique_ptr<Task> task(CreateTask(GetParam())); | 311 std::unique_ptr<Task> task(CreateTask(GetParam())); |
273 EXPECT_TRUE(tracker_.WillPostTask(task.get())); | 312 EXPECT_TRUE(tracker_.WillPostTask(task.get())); |
274 | 313 |
275 // Run the BLOCK_SHUTDOWN task. | 314 // Run the BLOCK_SHUTDOWN task. |
276 EXPECT_EQ(0U, num_tasks_executed_); | 315 EXPECT_EQ(0U, NumTasksExecuted()); |
277 tracker_.RunTask(task.get()); | 316 tracker_.RunTask(task.get()); |
278 EXPECT_EQ(1U, num_tasks_executed_); | 317 EXPECT_EQ(1U, NumTasksExecuted()); |
279 } else { | 318 } else { |
280 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task. | 319 // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task. |
281 std::unique_ptr<Task> task(CreateTask(GetParam())); | 320 std::unique_ptr<Task> task(CreateTask(GetParam())); |
282 EXPECT_FALSE(tracker_.WillPostTask(task.get())); | 321 EXPECT_FALSE(tracker_.WillPostTask(task.get())); |
283 | 322 |
284 // Don't try to run the task, because it wasn't allowed to be posted. | 323 // Don't try to run the task, because it wasn't allowed to be posted. |
285 } | 324 } |
286 | 325 |
287 // Unblock shutdown by running |block_shutdown_task|. | 326 // Unblock shutdown by running |block_shutdown_task|. |
288 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 327 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
289 tracker_.RunTask(block_shutdown_task.get()); | 328 tracker_.RunTask(block_shutdown_task.get()); |
290 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, | 329 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, |
291 num_tasks_executed_); | 330 NumTasksExecuted()); |
292 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 331 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
293 } | 332 } |
294 | 333 |
295 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) { | 334 TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) { |
296 tracker_.Shutdown(); | 335 tracker_.Shutdown(); |
297 | 336 |
298 std::unique_ptr<Task> task(CreateTask(GetParam())); | 337 std::unique_ptr<Task> task(CreateTask(GetParam())); |
299 | 338 |
300 // |task_tracker_| shouldn't allow a task to be posted after shutdown. | 339 // |task_tracker_| shouldn't allow a task to be posted after shutdown. |
301 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { | 340 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
415 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); | 454 ::testing::Values(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
416 INSTANTIATE_TEST_CASE_P( | 455 INSTANTIATE_TEST_CASE_P( |
417 SkipOnShutdown, | 456 SkipOnShutdown, |
418 TaskSchedulerTaskTrackerTest, | 457 TaskSchedulerTaskTrackerTest, |
419 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); | 458 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
420 INSTANTIATE_TEST_CASE_P( | 459 INSTANTIATE_TEST_CASE_P( |
421 BlockShutdown, | 460 BlockShutdown, |
422 TaskSchedulerTaskTrackerTest, | 461 TaskSchedulerTaskTrackerTest, |
423 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 462 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
424 | 463 |
464 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunBeforeShutdown) { | |
465 // Post and run tasks asynchronously. | |
466 std::vector<std::unique_ptr<Task>> tasks; | |
467 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; | |
468 | |
469 for (size_t i = 0; i < kLoadTestNumIterations; ++i) { | |
470 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); | |
471 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
472 &tracker_, tasks.back().get(), | |
473 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true))); | |
474 threads.back()->Start(); | |
475 | |
476 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); | |
477 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
478 &tracker_, tasks.back().get(), | |
479 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true))); | |
480 threads.back()->Start(); | |
481 | |
482 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
483 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
484 &tracker_, tasks.back().get(), | |
485 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true))); | |
486 threads.back()->Start(); | |
487 } | |
488 | |
489 for (const auto& thread : threads) | |
490 thread->Join(); | |
491 | |
492 // Expect all tasks to be executed. | |
493 EXPECT_EQ(kLoadTestNumIterations * 3, NumTasksExecuted()); | |
494 | |
495 // Should return immediately because no tasks are blocking shutdown. | |
496 tracker_.Shutdown(); | |
497 } | |
498 | |
499 TEST_F(TaskSchedulerTaskTrackerTest, | |
500 LoadWillPostBeforeShutdownAndRunDuringShutdown) { | |
501 // Post tasks asynchronously. | |
502 std::vector<std::unique_ptr<Task>> tasks; | |
503 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads; | |
504 | |
505 for (size_t i = 0; i < kLoadTestNumIterations; ++i) { | |
506 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); | |
507 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
508 &tracker_, tasks.back().get(), ThreadPostingAndRunningTask::WILL_POST, | |
509 true))); | |
510 post_threads.back()->Start(); | |
511 | |
512 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); | |
513 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
514 &tracker_, tasks.back().get(), ThreadPostingAndRunningTask::WILL_POST, | |
515 true))); | |
516 post_threads.back()->Start(); | |
517 | |
518 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
519 post_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
520 &tracker_, tasks.back().get(), ThreadPostingAndRunningTask::WILL_POST, | |
521 true))); | |
522 post_threads.back()->Start(); | |
523 } | |
524 | |
525 for (const auto& thread : post_threads) | |
526 thread->Join(); | |
527 | |
528 // Call Shutdown() asynchronously. | |
529 CallShutdownAsync(); | |
530 | |
531 // Run tasks asynchronously. | |
532 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads; | |
533 | |
534 for (const auto& task : tasks) { | |
535 run_threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
536 &tracker_, task.get(), ThreadPostingAndRunningTask::RUN, false))); | |
537 run_threads.back()->Start(); | |
538 } | |
539 | |
540 for (const auto& thread : run_threads) | |
541 thread->Join(); | |
542 | |
543 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | |
544 | |
545 // Expect BLOCK_SHUTDOWN tasks to have been executed. | |
546 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted()); | |
547 } | |
548 | |
549 TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) { | |
550 // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to | |
551 // block shutdown. | |
552 std::unique_ptr<Task> block_shutdown_task( | |
553 CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
554 EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); | |
555 | |
556 // Call Shutdown() asynchronously. | |
557 CallShutdownAsync(); | |
558 | |
559 // Post and run tasks asynchronously. | |
560 std::vector<std::unique_ptr<Task>> tasks; | |
561 std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> threads; | |
562 | |
563 for (size_t i = 0; i < kLoadTestNumIterations; ++i) { | |
564 tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); | |
565 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
566 &tracker_, tasks.back().get(), | |
567 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, false))); | |
568 threads.back()->Start(); | |
569 | |
570 tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); | |
571 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
572 &tracker_, tasks.back().get(), | |
573 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, false))); | |
574 threads.back()->Start(); | |
575 | |
576 tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | |
577 threads.push_back(WrapUnique(new ThreadPostingAndRunningTask( | |
578 &tracker_, tasks.back().get(), | |
579 ThreadPostingAndRunningTask::WILL_POST_AND_RUN, true))); | |
580 threads.back()->Start(); | |
581 } | |
582 | |
583 for (const auto& thread : threads) | |
584 thread->Join(); | |
585 | |
586 // Expect BLOCK_SHUTDOWN tasks to have been executed. | |
587 EXPECT_EQ(kLoadTestNumIterations, NumTasksExecuted()); | |
588 | |
589 // Shutdown() shouldn't return before |block_shutdown_task| is executed. | |
590 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | |
591 | |
592 // Unblock shutdown by running |block_shutdown_task|. | |
593 tracker_.RunTask(block_shutdown_task.get()); | |
594 EXPECT_EQ(kLoadTestNumIterations + 1, NumTasksExecuted()); | |
595 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | |
596 } | |
597 | |
425 } // namespace internal | 598 } // namespace internal |
426 } // namespace base | 599 } // namespace base |
OLD | NEW |