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 <queue> | 8 #include <queue> |
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/scoped_ptr.h" | 13 #include "base/memory/ptr_util.h" |
13 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
14 #include "base/task_scheduler/task.h" | 15 #include "base/task_scheduler/task.h" |
15 #include "base/task_scheduler/task_traits.h" | 16 #include "base/task_scheduler/task_traits.h" |
16 #include "base/task_scheduler/test_utils.h" | 17 #include "base/task_scheduler/test_utils.h" |
17 #include "base/threading/platform_thread.h" | 18 #include "base/threading/platform_thread.h" |
18 #include "base/threading/simple_thread.h" | 19 #include "base/threading/simple_thread.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
20 | 21 |
21 namespace base { | 22 namespace base { |
22 namespace internal { | 23 namespace internal { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 | 61 |
61 DISALLOW_COPY_AND_ASSIGN(ThreadRunningTask); | 62 DISALLOW_COPY_AND_ASSIGN(ThreadRunningTask); |
62 }; | 63 }; |
63 | 64 |
64 class TaskSchedulerTaskTrackerTest | 65 class TaskSchedulerTaskTrackerTest |
65 : public testing::TestWithParam<TaskShutdownBehavior> { | 66 : public testing::TestWithParam<TaskShutdownBehavior> { |
66 protected: | 67 protected: |
67 TaskSchedulerTaskTrackerTest() = default; | 68 TaskSchedulerTaskTrackerTest() = default; |
68 | 69 |
69 // Creates a task with |shutdown_behavior|. | 70 // Creates a task with |shutdown_behavior|. |
70 scoped_ptr<Task> CreateTask(TaskShutdownBehavior shutdown_behavior) { | 71 std::unique_ptr<Task> CreateTask(TaskShutdownBehavior shutdown_behavior) { |
71 return make_scoped_ptr(new Task( | 72 return WrapUnique(new Task( |
72 FROM_HERE, | 73 FROM_HERE, |
73 Bind(&TaskSchedulerTaskTrackerTest::RunTaskCallback, Unretained(this)), | 74 Bind(&TaskSchedulerTaskTrackerTest::RunTaskCallback, Unretained(this)), |
74 TaskTraits().WithShutdownBehavior(shutdown_behavior))); | 75 TaskTraits().WithShutdownBehavior(shutdown_behavior))); |
75 } | 76 } |
76 | 77 |
77 // Tries to post |task| via |tracker_|. If |tracker_| approves the operation, | 78 // Tries to post |task| via |tracker_|. If |tracker_| approves the operation, |
78 // |task| is added to |posted_tasks_|. | 79 // |task| is added to |posted_tasks_|. |
79 void PostTaskViaTracker(scoped_ptr<Task> task) { | 80 void PostTaskViaTracker(std::unique_ptr<Task> task) { |
80 tracker_.PostTask( | 81 tracker_.PostTask( |
81 Bind(&TaskSchedulerTaskTrackerTest::PostTaskCallback, Unretained(this)), | 82 Bind(&TaskSchedulerTaskTrackerTest::PostTaskCallback, Unretained(this)), |
82 std::move(task)); | 83 std::move(task)); |
83 } | 84 } |
84 | 85 |
85 // Tries to run the next task in |posted_tasks_| via |tracker_|. | 86 // Tries to run the next task in |posted_tasks_| via |tracker_|. |
86 void RunNextPostedTaskViaTracker() { | 87 void RunNextPostedTaskViaTracker() { |
87 ASSERT_FALSE(posted_tasks_.empty()); | 88 ASSERT_FALSE(posted_tasks_.empty()); |
88 tracker_.RunTask(posted_tasks_.front().get()); | 89 tracker_.RunTask(posted_tasks_.front().get()); |
89 posted_tasks_.pop(); | 90 posted_tasks_.pop(); |
(...skipping 21 matching lines...) Expand all Loading... |
111 | 112 |
112 void VerifyAsyncShutdownInProgress() { | 113 void VerifyAsyncShutdownInProgress() { |
113 ASSERT_TRUE(thread_calling_shutdown_); | 114 ASSERT_TRUE(thread_calling_shutdown_); |
114 EXPECT_FALSE(thread_calling_shutdown_->has_returned()); | 115 EXPECT_FALSE(thread_calling_shutdown_->has_returned()); |
115 EXPECT_FALSE(tracker_.shutdown_completed()); | 116 EXPECT_FALSE(tracker_.shutdown_completed()); |
116 EXPECT_TRUE(tracker_.IsShuttingDownForTesting()); | 117 EXPECT_TRUE(tracker_.IsShuttingDownForTesting()); |
117 } | 118 } |
118 | 119 |
119 TaskTracker tracker_; | 120 TaskTracker tracker_; |
120 size_t num_tasks_executed_ = 0; | 121 size_t num_tasks_executed_ = 0; |
121 std::queue<scoped_ptr<Task>> posted_tasks_; | 122 std::queue<std::unique_ptr<Task>> posted_tasks_; |
122 | 123 |
123 private: | 124 private: |
124 void PostTaskCallback(scoped_ptr<Task> task) { | 125 void PostTaskCallback(std::unique_ptr<Task> task) { |
125 posted_tasks_.push(std::move(task)); | 126 posted_tasks_.push(std::move(task)); |
126 } | 127 } |
127 | 128 |
128 void RunTaskCallback() { ++num_tasks_executed_; } | 129 void RunTaskCallback() { ++num_tasks_executed_; } |
129 | 130 |
130 scoped_ptr<ThreadCallingShutdown> thread_calling_shutdown_; | 131 std::unique_ptr<ThreadCallingShutdown> thread_calling_shutdown_; |
131 | 132 |
132 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest); | 133 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerTaskTrackerTest); |
133 }; | 134 }; |
134 | 135 |
135 #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \ | 136 #define WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED() \ |
136 do { \ | 137 do { \ |
137 SCOPED_TRACE(""); \ | 138 SCOPED_TRACE(""); \ |
138 WaitForAsyncShutdownCompleted(); \ | 139 WaitForAsyncShutdownCompleted(); \ |
139 } while (false) | 140 } while (false) |
140 | 141 |
141 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \ | 142 #define VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS() \ |
142 do { \ | 143 do { \ |
143 SCOPED_TRACE(""); \ | 144 SCOPED_TRACE(""); \ |
144 VerifyAsyncShutdownInProgress(); \ | 145 VerifyAsyncShutdownInProgress(); \ |
145 } while (false) | 146 } while (false) |
146 | 147 |
147 } // namespace | 148 } // namespace |
148 | 149 |
149 TEST_P(TaskSchedulerTaskTrackerTest, PostAndRunBeforeShutdown) { | 150 TEST_P(TaskSchedulerTaskTrackerTest, PostAndRunBeforeShutdown) { |
150 scoped_ptr<Task> task_to_post(CreateTask(GetParam())); | 151 std::unique_ptr<Task> task_to_post(CreateTask(GetParam())); |
151 const Task* task_to_post_raw = task_to_post.get(); | 152 const Task* task_to_post_raw = task_to_post.get(); |
152 | 153 |
153 // Post the task. | 154 // Post the task. |
154 EXPECT_TRUE(posted_tasks_.empty()); | 155 EXPECT_TRUE(posted_tasks_.empty()); |
155 PostTaskViaTracker(std::move(task_to_post)); | 156 PostTaskViaTracker(std::move(task_to_post)); |
156 EXPECT_EQ(1U, posted_tasks_.size()); | 157 EXPECT_EQ(1U, posted_tasks_.size()); |
157 EXPECT_EQ(task_to_post_raw, posted_tasks_.front().get()); | 158 EXPECT_EQ(task_to_post_raw, posted_tasks_.front().get()); |
158 | 159 |
159 // Run the posted task. | 160 // Run the posted task. |
160 EXPECT_EQ(0U, num_tasks_executed_); | 161 EXPECT_EQ(0U, num_tasks_executed_); |
161 RunNextPostedTaskViaTracker(); | 162 RunNextPostedTaskViaTracker(); |
162 EXPECT_EQ(1U, num_tasks_executed_); | 163 EXPECT_EQ(1U, num_tasks_executed_); |
163 | 164 |
164 // Shutdown() shouldn't block. | 165 // Shutdown() shouldn't block. |
165 tracker_.Shutdown(); | 166 tracker_.Shutdown(); |
166 } | 167 } |
167 | 168 |
168 TEST_P(TaskSchedulerTaskTrackerTest, PostAndRunLongTaskBeforeShutdown) { | 169 TEST_P(TaskSchedulerTaskTrackerTest, PostAndRunLongTaskBeforeShutdown) { |
169 // Post a task that will block until |event| is signaled. | 170 // Post a task that will block until |event| is signaled. |
170 EXPECT_TRUE(posted_tasks_.empty()); | 171 EXPECT_TRUE(posted_tasks_.empty()); |
171 WaitableEvent event(false, false); | 172 WaitableEvent event(false, false); |
172 PostTaskViaTracker(make_scoped_ptr( | 173 PostTaskViaTracker(WrapUnique( |
173 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)), | 174 new Task(FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&event)), |
174 TaskTraits().WithShutdownBehavior(GetParam())))); | 175 TaskTraits().WithShutdownBehavior(GetParam())))); |
175 EXPECT_EQ(1U, posted_tasks_.size()); | 176 EXPECT_EQ(1U, posted_tasks_.size()); |
176 | 177 |
177 // Run the task asynchronouly. | 178 // Run the task asynchronouly. |
178 ThreadRunningTask thread_running_task(&tracker_, posted_tasks_.front().get()); | 179 ThreadRunningTask thread_running_task(&tracker_, posted_tasks_.front().get()); |
179 thread_running_task.Start(); | 180 thread_running_task.Start(); |
180 | 181 |
181 // Initiate shutdown while the task is running. | 182 // Initiate shutdown while the task is running. |
182 CallShutdownAsync(); | 183 CallShutdownAsync(); |
183 | 184 |
184 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { | 185 if (GetParam() == TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) { |
185 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. | 186 // Shutdown should complete even with a CONTINUE_ON_SHUTDOWN in progress. |
186 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 187 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
187 } else { | 188 } else { |
188 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. | 189 // Shutdown should block with any non CONTINUE_ON_SHUTDOWN task in progress. |
189 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 190 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
190 } | 191 } |
191 | 192 |
192 // Unblock the task. | 193 // Unblock the task. |
193 event.Signal(); | 194 event.Signal(); |
194 thread_running_task.Join(); | 195 thread_running_task.Join(); |
195 | 196 |
196 // Shutdown should now complete for a non CONTINUE_ON_SHUTDOWN task. | 197 // Shutdown should now complete for a non CONTINUE_ON_SHUTDOWN task. |
197 if (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) | 198 if (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN) |
198 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 199 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
199 } | 200 } |
200 | 201 |
201 TEST_P(TaskSchedulerTaskTrackerTest, PostBeforeShutdownRunDuringShutdown) { | 202 TEST_P(TaskSchedulerTaskTrackerTest, PostBeforeShutdownRunDuringShutdown) { |
202 scoped_ptr<Task> task_to_post(CreateTask(GetParam())); | 203 std::unique_ptr<Task> task_to_post(CreateTask(GetParam())); |
203 const Task* task_to_post_raw = task_to_post.get(); | 204 const Task* task_to_post_raw = task_to_post.get(); |
204 | 205 |
205 // Post the task. | 206 // Post the task. |
206 EXPECT_TRUE(posted_tasks_.empty()); | 207 EXPECT_TRUE(posted_tasks_.empty()); |
207 PostTaskViaTracker(std::move(task_to_post)); | 208 PostTaskViaTracker(std::move(task_to_post)); |
208 EXPECT_EQ(1U, posted_tasks_.size()); | 209 EXPECT_EQ(1U, posted_tasks_.size()); |
209 EXPECT_EQ(task_to_post_raw, posted_tasks_.front().get()); | 210 EXPECT_EQ(task_to_post_raw, posted_tasks_.front().get()); |
210 | 211 |
211 // Post a BLOCK_SHUTDOWN task just to block shutdown. | 212 // Post a BLOCK_SHUTDOWN task just to block shutdown. |
212 PostTaskViaTracker(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 213 PostTaskViaTracker(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
(...skipping 11 matching lines...) Expand all Loading... |
224 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 225 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
225 | 226 |
226 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. | 227 // Unblock shutdown by running the remaining BLOCK_SHUTDOWN task. |
227 RunNextPostedTaskViaTracker(); | 228 RunNextPostedTaskViaTracker(); |
228 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, | 229 EXPECT_EQ(GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? 2U : 1U, |
229 num_tasks_executed_); | 230 num_tasks_executed_); |
230 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); | 231 WAIT_FOR_ASYNC_SHUTDOWN_COMPLETED(); |
231 } | 232 } |
232 | 233 |
233 TEST_P(TaskSchedulerTaskTrackerTest, PostBeforeShutdownRunAfterShutdown) { | 234 TEST_P(TaskSchedulerTaskTrackerTest, PostBeforeShutdownRunAfterShutdown) { |
234 scoped_ptr<Task> task_to_post(CreateTask(GetParam())); | 235 std::unique_ptr<Task> task_to_post(CreateTask(GetParam())); |
235 const Task* task_to_post_raw = task_to_post.get(); | 236 const Task* task_to_post_raw = task_to_post.get(); |
236 | 237 |
237 // Post the task. | 238 // Post the task. |
238 EXPECT_TRUE(posted_tasks_.empty()); | 239 EXPECT_TRUE(posted_tasks_.empty()); |
239 PostTaskViaTracker(std::move(task_to_post)); | 240 PostTaskViaTracker(std::move(task_to_post)); |
240 EXPECT_EQ(1U, posted_tasks_.size()); | 241 EXPECT_EQ(1U, posted_tasks_.size()); |
241 EXPECT_EQ(task_to_post_raw, posted_tasks_.front().get()); | 242 EXPECT_EQ(task_to_post_raw, posted_tasks_.front().get()); |
242 | 243 |
243 // Call Shutdown() asynchronously. | 244 // Call Shutdown() asynchronously. |
244 CallShutdownAsync(); | 245 CallShutdownAsync(); |
(...skipping 15 matching lines...) Expand all Loading... |
260 | 261 |
261 // The task shouldn't be allowed to run after shutdown. | 262 // The task shouldn't be allowed to run after shutdown. |
262 RunNextPostedTaskViaTracker(); | 263 RunNextPostedTaskViaTracker(); |
263 EXPECT_EQ(0U, num_tasks_executed_); | 264 EXPECT_EQ(0U, num_tasks_executed_); |
264 } | 265 } |
265 } | 266 } |
266 | 267 |
267 TEST_P(TaskSchedulerTaskTrackerTest, PostAndRunDuringShutdown) { | 268 TEST_P(TaskSchedulerTaskTrackerTest, PostAndRunDuringShutdown) { |
268 // Post a BLOCK_SHUTDOWN task just to block shutdown. | 269 // Post a BLOCK_SHUTDOWN task just to block shutdown. |
269 PostTaskViaTracker(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 270 PostTaskViaTracker(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
270 scoped_ptr<Task> block_shutdown_task = std::move(posted_tasks_.front()); | 271 std::unique_ptr<Task> block_shutdown_task = std::move(posted_tasks_.front()); |
271 posted_tasks_.pop(); | 272 posted_tasks_.pop(); |
272 | 273 |
273 // Call Shutdown() asynchronously. | 274 // Call Shutdown() asynchronously. |
274 CallShutdownAsync(); | 275 CallShutdownAsync(); |
275 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); | 276 VERIFY_ASYNC_SHUTDOWN_IN_PROGRESS(); |
276 | 277 |
277 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { | 278 if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { |
278 // Post a BLOCK_SHUTDOWN task. This should succeed. | 279 // Post a BLOCK_SHUTDOWN task. This should succeed. |
279 EXPECT_TRUE(posted_tasks_.empty()); | 280 EXPECT_TRUE(posted_tasks_.empty()); |
280 PostTaskViaTracker(CreateTask(GetParam())); | 281 PostTaskViaTracker(CreateTask(GetParam())); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 SkipOnShutdown, | 324 SkipOnShutdown, |
324 TaskSchedulerTaskTrackerTest, | 325 TaskSchedulerTaskTrackerTest, |
325 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); | 326 ::testing::Values(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
326 INSTANTIATE_TEST_CASE_P( | 327 INSTANTIATE_TEST_CASE_P( |
327 BlockShutdown, | 328 BlockShutdown, |
328 TaskSchedulerTaskTrackerTest, | 329 TaskSchedulerTaskTrackerTest, |
329 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN)); | 330 ::testing::Values(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
330 | 331 |
331 } // namespace internal | 332 } // namespace internal |
332 } // namespace base | 333 } // namespace base |
OLD | NEW |