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

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

Issue 2806413002: Separate the create and start phases in SchedulerSingleThreadTaskRunnerManager. (Closed)
Patch Set: self-review Created 3 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
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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_single_thread_task_runner_manager.h" 5 #include "base/task_scheduler/scheduler_single_thread_task_runner_manager.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/synchronization/atomic_flag.h"
9 #include "base/synchronization/lock.h" 10 #include "base/synchronization/lock.h"
10 #include "base/synchronization/waitable_event.h" 11 #include "base/synchronization/waitable_event.h"
11 #include "base/task_scheduler/delayed_task_manager.h" 12 #include "base/task_scheduler/delayed_task_manager.h"
12 #include "base/task_scheduler/post_task.h" 13 #include "base/task_scheduler/post_task.h"
13 #include "base/task_scheduler/scheduler_worker_pool_params.h" 14 #include "base/task_scheduler/scheduler_worker_pool_params.h"
14 #include "base/task_scheduler/task_tracker.h" 15 #include "base/task_scheduler/task_tracker.h"
15 #include "base/task_scheduler/task_traits.h" 16 #include "base/task_scheduler/task_traits.h"
16 #include "base/test/test_timeouts.h" 17 #include "base/test/test_timeouts.h"
18 #include "base/threading/platform_thread.h"
17 #include "base/threading/simple_thread.h" 19 #include "base/threading/simple_thread.h"
18 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
19 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
20 22
21 #if defined(OS_WIN) 23 #if defined(OS_WIN)
22 #include <windows.h> 24 #include <windows.h>
23 #include <objbase.h> 25 #include <objbase.h>
24 26
25 #include "base/win/current_module.h" 27 #include "base/win/current_module.h"
26 #endif // defined(OS_WIN) 28 #endif // defined(OS_WIN)
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 *thread_priority = PlatformThread::GetCurrentThreadPriority(); 107 *thread_priority = PlatformThread::GetCurrentThreadPriority();
106 } 108 }
107 109
108 void ShouldNotRun() { 110 void ShouldNotRun() {
109 ADD_FAILURE() << "Ran a task that shouldn't run."; 111 ADD_FAILURE() << "Ran a task that shouldn't run.";
110 } 112 }
111 113
112 } // namespace 114 } // namespace
113 115
114 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) { 116 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, DifferentThreadsUsed) {
117 single_thread_task_runner_manager_->Start();
robliao 2017/04/10 20:52:48 Given the majority of the tests start the task run
fdoray 2017/04/11 15:27:24 Done.
115 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = 118 scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
116 single_thread_task_runner_manager_ 119 single_thread_task_runner_manager_
117 ->CreateSingleThreadTaskRunnerWithTraits( 120 ->CreateSingleThreadTaskRunnerWithTraits(
118 TaskTraits().WithShutdownBehavior( 121 TaskTraits().WithShutdownBehavior(
119 TaskShutdownBehavior::BLOCK_SHUTDOWN)); 122 TaskShutdownBehavior::BLOCK_SHUTDOWN));
120 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = 123 scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
121 single_thread_task_runner_manager_ 124 single_thread_task_runner_manager_
122 ->CreateSingleThreadTaskRunnerWithTraits( 125 ->CreateSingleThreadTaskRunnerWithTraits(
123 TaskTraits().WithShutdownBehavior( 126 TaskTraits().WithShutdownBehavior(
124 TaskShutdownBehavior::BLOCK_SHUTDOWN)); 127 TaskShutdownBehavior::BLOCK_SHUTDOWN));
125 128
126 PlatformThreadRef thread_ref_1; 129 PlatformThreadRef thread_ref_1;
127 task_runner_1->PostTask(FROM_HERE, Bind(&CaptureThreadRef, &thread_ref_1)); 130 task_runner_1->PostTask(FROM_HERE, Bind(&CaptureThreadRef, &thread_ref_1));
128 PlatformThreadRef thread_ref_2; 131 PlatformThreadRef thread_ref_2;
129 task_runner_2->PostTask(FROM_HERE, Bind(&CaptureThreadRef, &thread_ref_2)); 132 task_runner_2->PostTask(FROM_HERE, Bind(&CaptureThreadRef, &thread_ref_2));
130 133
131 task_tracker_.Shutdown(); 134 task_tracker_.Shutdown();
132 135
133 ASSERT_FALSE(thread_ref_1.is_null()); 136 ASSERT_FALSE(thread_ref_1.is_null());
134 ASSERT_FALSE(thread_ref_2.is_null()); 137 ASSERT_FALSE(thread_ref_2.is_null());
135 EXPECT_NE(thread_ref_1, thread_ref_2); 138 EXPECT_NE(thread_ref_1, thread_ref_2);
136 } 139 }
137 140
138 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PrioritySetCorrectly) { 141 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PrioritySetCorrectly) {
142 single_thread_task_runner_manager_->Start();
139 // Why are events used here instead of the task tracker? 143 // Why are events used here instead of the task tracker?
140 // Shutting down can cause priorities to get raised. This means we have to use 144 // Shutting down can cause priorities to get raised. This means we have to use
141 // events to determine when a task is run. 145 // events to determine when a task is run.
142 scoped_refptr<SingleThreadTaskRunner> task_runner_background = 146 scoped_refptr<SingleThreadTaskRunner> task_runner_background =
143 single_thread_task_runner_manager_ 147 single_thread_task_runner_manager_
144 ->CreateSingleThreadTaskRunnerWithTraits( 148 ->CreateSingleThreadTaskRunnerWithTraits(
145 TaskTraits().WithPriority(TaskPriority::BACKGROUND)); 149 TaskTraits().WithPriority(TaskPriority::BACKGROUND));
146 scoped_refptr<SingleThreadTaskRunner> task_runner_user_visible = 150 scoped_refptr<SingleThreadTaskRunner> task_runner_user_visible =
147 single_thread_task_runner_manager_ 151 single_thread_task_runner_manager_
148 ->CreateSingleThreadTaskRunnerWithTraits( 152 ->CreateSingleThreadTaskRunnerWithTraits(
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 waitable_event_user_blocking.Wait(); 193 waitable_event_user_blocking.Wait();
190 194
191 if (Lock::HandlesMultipleThreadPriorities()) 195 if (Lock::HandlesMultipleThreadPriorities())
192 EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background); 196 EXPECT_EQ(ThreadPriority::BACKGROUND, thread_priority_background);
193 else 197 else
194 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background); 198 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_background);
195 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_visible); 199 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_visible);
196 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_blocking); 200 EXPECT_EQ(ThreadPriority::NORMAL, thread_priority_user_blocking);
197 } 201 }
198 202
203 // Verify that a task posted before Start() doesn't run until Start() is called.
204 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostTaskBeforeStart) {
205 AtomicFlag manager_started;
206 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL,
207 WaitableEvent::InitialState::NOT_SIGNALED);
208 single_thread_task_runner_manager_
209 ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits())
210 ->PostTask(
211 FROM_HERE,
212 Bind(
213 [](WaitableEvent* task_running, AtomicFlag* manager_started) {
214 task_running->Signal();
215
216 // The task should not run before Start().
217 EXPECT_TRUE(manager_started->IsSet());
218 },
219 Unretained(&task_running), Unretained(&manager_started)));
220
221 // Wait a little bit to make sure that the task isn't scheduled before start.
222 // Note: This test won't catch a case where the task is scheduled between
223 // setting |manager_started| and calling Start(). However, we expect the test
224 // to be flaky if the tested code allows that to happen.
225 PlatformThread::Sleep(TestTimeouts::tiny_timeout());
226 manager_started.Set();
227 single_thread_task_runner_manager_->Start();
228
229 // This should not hang if the task is scheduled after Start().
230 task_running.Wait();
231 }
232
199 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostTaskAfterShutdown) { 233 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostTaskAfterShutdown) {
234 single_thread_task_runner_manager_->Start();
200 auto task_runner = single_thread_task_runner_manager_ 235 auto task_runner = single_thread_task_runner_manager_
201 ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); 236 ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits());
202 task_tracker_.Shutdown(); 237 task_tracker_.Shutdown();
203 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, Bind(&ShouldNotRun))); 238 EXPECT_FALSE(task_runner->PostTask(FROM_HERE, Bind(&ShouldNotRun)));
204 } 239 }
205 240
206 // Verify that a Task runs shortly after its delay expires. 241 // Verify that a Task runs shortly after its delay expires.
207 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostDelayedTask) { 242 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, PostDelayedTask) {
243 single_thread_task_runner_manager_->Start();
208 TimeTicks start_time = TimeTicks::Now(); 244 TimeTicks start_time = TimeTicks::Now();
209 245
210 // Post a task with a short delay. 246 // Post a task with a short delay.
211 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL, 247 WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL,
212 WaitableEvent::InitialState::NOT_SIGNALED); 248 WaitableEvent::InitialState::NOT_SIGNALED);
213 auto task_runner = single_thread_task_runner_manager_ 249 auto task_runner = single_thread_task_runner_manager_
214 ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); 250 ->CreateSingleThreadTaskRunnerWithTraits(TaskTraits());
215 EXPECT_TRUE(task_runner->PostDelayedTask( 251 EXPECT_TRUE(task_runner->PostDelayedTask(
216 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_ran)), 252 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_ran)),
217 TestTimeouts::tiny_timeout())); 253 TestTimeouts::tiny_timeout()));
218 254
219 // Wait until the task runs. 255 // Wait until the task runs.
220 task_ran.Wait(); 256 task_ran.Wait();
221 257
222 // Expect the task to run after its delay expires, but not more than 250 ms 258 // Expect the task to run after its delay expires, but not more than 250 ms
223 // after that. 259 // after that.
224 const TimeDelta actual_delay = TimeTicks::Now() - start_time; 260 const TimeDelta actual_delay = TimeTicks::Now() - start_time;
225 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout()); 261 EXPECT_GE(actual_delay, TestTimeouts::tiny_timeout());
226 EXPECT_LT(actual_delay, 262 EXPECT_LT(actual_delay,
227 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout()); 263 TimeDelta::FromMilliseconds(250) + TestTimeouts::tiny_timeout());
228 } 264 }
229 265
230 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, 266 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest,
231 RunsTasksOnCurrentThread) { 267 RunsTasksOnCurrentThread) {
268 single_thread_task_runner_manager_->Start();
232 scoped_refptr<SingleThreadTaskRunner> task_runner_1 = 269 scoped_refptr<SingleThreadTaskRunner> task_runner_1 =
233 single_thread_task_runner_manager_ 270 single_thread_task_runner_manager_
234 ->CreateSingleThreadTaskRunnerWithTraits( 271 ->CreateSingleThreadTaskRunnerWithTraits(
235 TaskTraits().WithShutdownBehavior( 272 TaskTraits().WithShutdownBehavior(
236 TaskShutdownBehavior::BLOCK_SHUTDOWN)); 273 TaskShutdownBehavior::BLOCK_SHUTDOWN));
237 scoped_refptr<SingleThreadTaskRunner> task_runner_2 = 274 scoped_refptr<SingleThreadTaskRunner> task_runner_2 =
238 single_thread_task_runner_manager_ 275 single_thread_task_runner_manager_
239 ->CreateSingleThreadTaskRunnerWithTraits( 276 ->CreateSingleThreadTaskRunnerWithTraits(
240 TaskTraits().WithShutdownBehavior( 277 TaskTraits().WithShutdownBehavior(
241 TaskShutdownBehavior::BLOCK_SHUTDOWN)); 278 TaskShutdownBehavior::BLOCK_SHUTDOWN));
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 single_thread_task_runner_manager_.reset(); 340 single_thread_task_runner_manager_.reset();
304 } 341 }
305 342
306 private: 343 private:
307 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest); 344 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest);
308 }; 345 };
309 346
310 } // namespace 347 } // namespace
311 348
312 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) { 349 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, ConcurrentJoin) {
350 single_thread_task_runner_manager_->Start();
313 // Exercises the codepath where the workers are unavailable for unregistration 351 // Exercises the codepath where the workers are unavailable for unregistration
314 // because of a Join call. 352 // because of a Join call.
315 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, 353 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL,
316 WaitableEvent::InitialState::NOT_SIGNALED); 354 WaitableEvent::InitialState::NOT_SIGNALED);
317 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, 355 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL,
318 WaitableEvent::InitialState::NOT_SIGNALED); 356 WaitableEvent::InitialState::NOT_SIGNALED);
319 357
320 { 358 {
321 auto task_runner = single_thread_task_runner_manager_ 359 auto task_runner = single_thread_task_runner_manager_
322 ->CreateSingleThreadTaskRunnerWithTraits( 360 ->CreateSingleThreadTaskRunnerWithTraits(
323 TaskTraits().WithBaseSyncPrimitives()); 361 TaskTraits().WithBaseSyncPrimitives());
324 EXPECT_TRUE(task_runner->PostTask( 362 EXPECT_TRUE(task_runner->PostTask(
325 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_running)))); 363 FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&task_running))));
326 EXPECT_TRUE(task_runner->PostTask( 364 EXPECT_TRUE(task_runner->PostTask(
327 FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&task_blocking)))); 365 FROM_HERE, Bind(&WaitableEvent::Wait, Unretained(&task_blocking))));
328 } 366 }
329 367
330 task_running.Wait(); 368 task_running.Wait();
331 CallJoinFromDifferentThread join_from_different_thread( 369 CallJoinFromDifferentThread join_from_different_thread(
332 single_thread_task_runner_manager_.get()); 370 single_thread_task_runner_manager_.get());
333 join_from_different_thread.Start(); 371 join_from_different_thread.Start();
334 join_from_different_thread.WaitForRunToStart(); 372 join_from_different_thread.WaitForRunToStart();
335 task_blocking.Signal(); 373 task_blocking.Signal();
336 join_from_different_thread.Join(); 374 join_from_different_thread.Join();
337 } 375 }
338 376
339 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest, 377 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerJoinTest,
340 ConcurrentJoinExtraSkippedTask) { 378 ConcurrentJoinExtraSkippedTask) {
379 single_thread_task_runner_manager_->Start();
341 // Tests to make sure that tasks are properly cleaned up at Join, allowing 380 // Tests to make sure that tasks are properly cleaned up at Join, allowing
342 // SingleThreadTaskRunners to unregister themselves. 381 // SingleThreadTaskRunners to unregister themselves.
343 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL, 382 WaitableEvent task_running(WaitableEvent::ResetPolicy::MANUAL,
344 WaitableEvent::InitialState::NOT_SIGNALED); 383 WaitableEvent::InitialState::NOT_SIGNALED);
345 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL, 384 WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL,
346 WaitableEvent::InitialState::NOT_SIGNALED); 385 WaitableEvent::InitialState::NOT_SIGNALED);
347 386
348 { 387 {
349 auto task_runner = single_thread_task_runner_manager_ 388 auto task_runner = single_thread_task_runner_manager_
350 ->CreateSingleThreadTaskRunnerWithTraits( 389 ->CreateSingleThreadTaskRunnerWithTraits(
(...skipping 10 matching lines...) Expand all
361 single_thread_task_runner_manager_.get()); 400 single_thread_task_runner_manager_.get());
362 join_from_different_thread.Start(); 401 join_from_different_thread.Start();
363 join_from_different_thread.WaitForRunToStart(); 402 join_from_different_thread.WaitForRunToStart();
364 task_blocking.Signal(); 403 task_blocking.Signal();
365 join_from_different_thread.Join(); 404 join_from_different_thread.Join();
366 } 405 }
367 406
368 #if defined(OS_WIN) 407 #if defined(OS_WIN)
369 408
370 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTAInitialized) { 409 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTest, COMSTAInitialized) {
410 single_thread_task_runner_manager_->Start();
371 scoped_refptr<SingleThreadTaskRunner> com_task_runner = 411 scoped_refptr<SingleThreadTaskRunner> com_task_runner =
372 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( 412 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits(
373 TaskTraits().WithShutdownBehavior( 413 TaskTraits().WithShutdownBehavior(
374 TaskShutdownBehavior::BLOCK_SHUTDOWN)); 414 TaskShutdownBehavior::BLOCK_SHUTDOWN));
375 415
376 com_task_runner->PostTask( 416 com_task_runner->PostTask(
377 FROM_HERE, Bind([]() { 417 FROM_HERE, Bind([]() {
378 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); 418 HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
379 if (SUCCEEDED(hr)) { 419 if (SUCCEEDED(hr)) {
380 ADD_FAILURE() << "COM STA was not initialized on this thread"; 420 ADD_FAILURE() << "COM STA was not initialized on this thread";
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 } 464 }
425 465
426 bool register_class_succeeded_ = false; 466 bool register_class_succeeded_ = false;
427 467
428 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin); 468 DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSingleThreadTaskRunnerManagerTestWin);
429 }; 469 };
430 470
431 } // namespace 471 } // namespace
432 472
433 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) { 473 TEST_F(TaskSchedulerSingleThreadTaskRunnerManagerTestWin, PumpsMessages) {
474 single_thread_task_runner_manager_->Start();
434 scoped_refptr<SingleThreadTaskRunner> com_task_runner = 475 scoped_refptr<SingleThreadTaskRunner> com_task_runner =
435 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits( 476 single_thread_task_runner_manager_->CreateCOMSTATaskRunnerWithTraits(
436 TaskTraits().WithShutdownBehavior( 477 TaskTraits().WithShutdownBehavior(
437 TaskShutdownBehavior::BLOCK_SHUTDOWN)); 478 TaskShutdownBehavior::BLOCK_SHUTDOWN));
438 HWND hwnd = nullptr; 479 HWND hwnd = nullptr;
439 // HWNDs process messages on the thread that created them, so we have to 480 // HWNDs process messages on the thread that created them, so we have to
440 // create them within the context of the task runner to properly simulate a 481 // create them within the context of the task runner to properly simulate a
441 // COM callback. 482 // COM callback.
442 com_task_runner->PostTask( 483 com_task_runner->PostTask(
443 FROM_HERE, 484 FROM_HERE,
(...skipping 11 matching lines...) Expand all
455 com_task_runner->PostTask( 496 com_task_runner->PostTask(
456 FROM_HERE, Bind([](HWND hwnd) { ::DestroyWindow(hwnd); }, hwnd)); 497 FROM_HERE, Bind([](HWND hwnd) { ::DestroyWindow(hwnd); }, hwnd));
457 498
458 task_tracker_.Shutdown(); 499 task_tracker_.Shutdown();
459 } 500 }
460 501
461 #endif // defined(OS_WIN) 502 #endif // defined(OS_WIN)
462 503
463 } // namespace internal 504 } // namespace internal
464 } // namespace base 505 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698