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

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

Powered by Google App Engine
This is Rietveld 408576698