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