OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/threading/thread.h" | 5 #include "base/threading/thread.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <vector> | 10 #include <vector> |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 options.stack_size = 2 * 3072 * sizeof(uintptr_t); | 148 options.stack_size = 2 * 3072 * sizeof(uintptr_t); |
149 #else | 149 #else |
150 options.stack_size = 3072 * sizeof(uintptr_t); | 150 options.stack_size = 3072 * sizeof(uintptr_t); |
151 #endif | 151 #endif |
152 EXPECT_TRUE(a.StartWithOptions(options)); | 152 EXPECT_TRUE(a.StartWithOptions(options)); |
153 EXPECT_TRUE(a.message_loop()); | 153 EXPECT_TRUE(a.message_loop()); |
154 EXPECT_TRUE(a.IsRunning()); | 154 EXPECT_TRUE(a.IsRunning()); |
155 | 155 |
156 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, | 156 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
157 base::WaitableEvent::InitialState::NOT_SIGNALED); | 157 base::WaitableEvent::InitialState::NOT_SIGNALED); |
158 a.task_runner()->PostTask(FROM_HERE, base::Bind(&base::WaitableEvent::Signal, | 158 a.task_runner()->PostTask( |
159 base::Unretained(&event))); | 159 FROM_HERE, |
| 160 base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event))); |
160 event.Wait(); | 161 event.Wait(); |
161 } | 162 } |
162 | 163 |
163 // Intentional test-only race for otherwise untestable code, won't fix. | 164 // Intentional test-only race for otherwise untestable code, won't fix. |
164 // https://crbug.com/634383 | 165 // https://crbug.com/634383 |
165 #if !defined(THREAD_SANITIZER) | 166 #if !defined(THREAD_SANITIZER) |
166 TEST_F(ThreadTest, StartWithOptions_NonJoinable) { | 167 TEST_F(ThreadTest, StartWithOptions_NonJoinable) { |
167 Thread* a = new Thread("StartNonJoinable"); | 168 Thread* a = new Thread("StartNonJoinable"); |
168 // Non-joinable threads have to be leaked for now (see | 169 // Non-joinable threads have to be leaked for now (see |
169 // Thread::Options::joinable for details). | 170 // Thread::Options::joinable for details). |
(...skipping 11 matching lines...) Expand all Loading... |
181 // satisfied and the real |is_running_| bit has to be checked. It could still | 182 // satisfied and the real |is_running_| bit has to be checked. It could still |
182 // be false if the message loop hasn't started for real in practice. This is | 183 // be false if the message loop hasn't started for real in practice. This is |
183 // only a requirement for this test because the non-joinable property forces | 184 // only a requirement for this test because the non-joinable property forces |
184 // it to use StopSoon() and not wait for a complete Stop(). | 185 // it to use StopSoon() and not wait for a complete Stop(). |
185 EXPECT_TRUE(a->WaitUntilThreadStarted()); | 186 EXPECT_TRUE(a->WaitUntilThreadStarted()); |
186 | 187 |
187 // Make the thread block until |block_event| is signaled. | 188 // Make the thread block until |block_event| is signaled. |
188 base::WaitableEvent block_event( | 189 base::WaitableEvent block_event( |
189 base::WaitableEvent::ResetPolicy::AUTOMATIC, | 190 base::WaitableEvent::ResetPolicy::AUTOMATIC, |
190 base::WaitableEvent::InitialState::NOT_SIGNALED); | 191 base::WaitableEvent::InitialState::NOT_SIGNALED); |
191 a->task_runner()->PostTask( | 192 a->task_runner()->PostTask(FROM_HERE, |
192 FROM_HERE, | 193 base::BindOnce(&base::WaitableEvent::Wait, |
193 base::Bind(&base::WaitableEvent::Wait, base::Unretained(&block_event))); | 194 base::Unretained(&block_event))); |
194 | 195 |
195 a->StopSoon(); | 196 a->StopSoon(); |
196 EXPECT_TRUE(a->IsRunning()); | 197 EXPECT_TRUE(a->IsRunning()); |
197 | 198 |
198 // Unblock the task and give a bit of extra time to unwind QuitWhenIdle(). | 199 // Unblock the task and give a bit of extra time to unwind QuitWhenIdle(). |
199 block_event.Signal(); | 200 block_event.Signal(); |
200 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); | 201 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); |
201 | 202 |
202 // The thread should now have stopped on its own. | 203 // The thread should now have stopped on its own. |
203 EXPECT_FALSE(a->IsRunning()); | 204 EXPECT_FALSE(a->IsRunning()); |
204 } | 205 } |
205 #endif | 206 #endif |
206 | 207 |
207 TEST_F(ThreadTest, TwoTasksOnJoinableThread) { | 208 TEST_F(ThreadTest, TwoTasksOnJoinableThread) { |
208 bool was_invoked = false; | 209 bool was_invoked = false; |
209 { | 210 { |
210 Thread a("TwoTasksOnJoinableThread"); | 211 Thread a("TwoTasksOnJoinableThread"); |
211 EXPECT_TRUE(a.Start()); | 212 EXPECT_TRUE(a.Start()); |
212 EXPECT_TRUE(a.message_loop()); | 213 EXPECT_TRUE(a.message_loop()); |
213 | 214 |
214 // Test that all events are dispatched before the Thread object is | 215 // Test that all events are dispatched before the Thread object is |
215 // destroyed. We do this by dispatching a sleep event before the | 216 // destroyed. We do this by dispatching a sleep event before the |
216 // event that will toggle our sentinel value. | 217 // event that will toggle our sentinel value. |
217 a.task_runner()->PostTask( | 218 a.task_runner()->PostTask( |
218 FROM_HERE, base::Bind(static_cast<void (*)(base::TimeDelta)>( | 219 FROM_HERE, base::BindOnce(static_cast<void (*)(base::TimeDelta)>( |
219 &base::PlatformThread::Sleep), | 220 &base::PlatformThread::Sleep), |
220 base::TimeDelta::FromMilliseconds(20))); | 221 base::TimeDelta::FromMilliseconds(20))); |
221 a.task_runner()->PostTask(FROM_HERE, | 222 a.task_runner()->PostTask(FROM_HERE, |
222 base::Bind(&ToggleValue, &was_invoked)); | 223 base::BindOnce(&ToggleValue, &was_invoked)); |
223 } | 224 } |
224 EXPECT_TRUE(was_invoked); | 225 EXPECT_TRUE(was_invoked); |
225 } | 226 } |
226 | 227 |
227 TEST_F(ThreadTest, DestroyWhileRunningIsSafe) { | 228 TEST_F(ThreadTest, DestroyWhileRunningIsSafe) { |
228 Thread a("DestroyWhileRunningIsSafe"); | 229 Thread a("DestroyWhileRunningIsSafe"); |
229 EXPECT_TRUE(a.Start()); | 230 EXPECT_TRUE(a.Start()); |
230 EXPECT_TRUE(a.WaitUntilThreadStarted()); | 231 EXPECT_TRUE(a.WaitUntilThreadStarted()); |
231 } | 232 } |
232 | 233 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 // TODO(gab): Enable this test in conjunction with re-enabling the sequence | 279 // TODO(gab): Enable this test in conjunction with re-enabling the sequence |
279 // check in Thread::Stop() as part of http://crbug.com/629139. | 280 // check in Thread::Stop() as part of http://crbug.com/629139. |
280 TEST_F(ThreadTest, DISABLED_StopOnNonOwningThreadIsDeath) { | 281 TEST_F(ThreadTest, DISABLED_StopOnNonOwningThreadIsDeath) { |
281 Thread a("StopOnNonOwningThreadDeath"); | 282 Thread a("StopOnNonOwningThreadDeath"); |
282 EXPECT_TRUE(a.StartAndWaitForTesting()); | 283 EXPECT_TRUE(a.StartAndWaitForTesting()); |
283 | 284 |
284 Thread b("NonOwningThread"); | 285 Thread b("NonOwningThread"); |
285 b.Start(); | 286 b.Start(); |
286 EXPECT_DCHECK_DEATH({ | 287 EXPECT_DCHECK_DEATH({ |
287 // Stopping |a| on |b| isn't allowed. | 288 // Stopping |a| on |b| isn't allowed. |
288 b.task_runner()->PostTask(FROM_HERE, | 289 b.task_runner()->PostTask( |
289 base::Bind(&Thread::Stop, base::Unretained(&a))); | 290 FROM_HERE, base::BindOnce(&Thread::Stop, base::Unretained(&a))); |
290 // Block here so the DCHECK on |b| always happens in this scope. | 291 // Block here so the DCHECK on |b| always happens in this scope. |
291 base::PlatformThread::Sleep(base::TimeDelta::Max()); | 292 base::PlatformThread::Sleep(base::TimeDelta::Max()); |
292 }); | 293 }); |
293 } | 294 } |
294 | 295 |
295 TEST_F(ThreadTest, TransferOwnershipAndStop) { | 296 TEST_F(ThreadTest, TransferOwnershipAndStop) { |
296 std::unique_ptr<Thread> a = | 297 std::unique_ptr<Thread> a = |
297 base::MakeUnique<Thread>("TransferOwnershipAndStop"); | 298 base::MakeUnique<Thread>("TransferOwnershipAndStop"); |
298 EXPECT_TRUE(a->StartAndWaitForTesting()); | 299 EXPECT_TRUE(a->StartAndWaitForTesting()); |
299 EXPECT_TRUE(a->IsRunning()); | 300 EXPECT_TRUE(a->IsRunning()); |
300 | 301 |
301 Thread b("TakingOwnershipThread"); | 302 Thread b("TakingOwnershipThread"); |
302 b.Start(); | 303 b.Start(); |
303 | 304 |
304 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, | 305 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, |
305 base::WaitableEvent::InitialState::NOT_SIGNALED); | 306 base::WaitableEvent::InitialState::NOT_SIGNALED); |
306 | 307 |
307 // a->DetachFromSequence() should allow |b| to use |a|'s Thread API. | 308 // a->DetachFromSequence() should allow |b| to use |a|'s Thread API. |
308 a->DetachFromSequence(); | 309 a->DetachFromSequence(); |
309 b.task_runner()->PostTask( | 310 b.task_runner()->PostTask( |
310 FROM_HERE, base::Bind( | 311 FROM_HERE, base::BindOnce( |
311 [](std::unique_ptr<Thread> thread_to_stop, | 312 [](std::unique_ptr<Thread> thread_to_stop, |
312 base::WaitableEvent* event_to_signal) -> void { | 313 base::WaitableEvent* event_to_signal) -> void { |
313 thread_to_stop->Stop(); | 314 thread_to_stop->Stop(); |
314 event_to_signal->Signal(); | 315 event_to_signal->Signal(); |
315 }, | 316 }, |
316 base::Passed(&a), base::Unretained(&event))); | 317 base::Passed(&a), base::Unretained(&event))); |
317 | 318 |
318 event.Wait(); | 319 event.Wait(); |
319 } | 320 } |
320 | 321 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 Thread::Options options; | 355 Thread::Options options; |
355 options.joinable = false; | 356 options.joinable = false; |
356 EXPECT_TRUE(a->StartWithOptions(options)); | 357 EXPECT_TRUE(a->StartWithOptions(options)); |
357 EXPECT_TRUE(a->message_loop()); | 358 EXPECT_TRUE(a->message_loop()); |
358 EXPECT_TRUE(a->IsRunning()); | 359 EXPECT_TRUE(a->IsRunning()); |
359 | 360 |
360 // Signaled when last task on |a| is processed. | 361 // Signaled when last task on |a| is processed. |
361 base::WaitableEvent last_task_event( | 362 base::WaitableEvent last_task_event( |
362 base::WaitableEvent::ResetPolicy::AUTOMATIC, | 363 base::WaitableEvent::ResetPolicy::AUTOMATIC, |
363 base::WaitableEvent::InitialState::NOT_SIGNALED); | 364 base::WaitableEvent::InitialState::NOT_SIGNALED); |
364 a->task_runner()->PostTask(FROM_HERE, | 365 a->task_runner()->PostTask( |
365 base::Bind(&base::WaitableEvent::Signal, | 366 FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal, |
366 base::Unretained(&last_task_event))); | 367 base::Unretained(&last_task_event))); |
367 | 368 |
368 // StopSoon() is non-blocking, Yield() to |a|, wait for last task to be | 369 // StopSoon() is non-blocking, Yield() to |a|, wait for last task to be |
369 // processed and a little more for QuitWhenIdle() to unwind before considering | 370 // processed and a little more for QuitWhenIdle() to unwind before considering |
370 // the thread "stopped". | 371 // the thread "stopped". |
371 a->StopSoon(); | 372 a->StopSoon(); |
372 base::PlatformThread::YieldCurrentThread(); | 373 base::PlatformThread::YieldCurrentThread(); |
373 last_task_event.Wait(); | 374 last_task_event.Wait(); |
374 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); | 375 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20)); |
375 | 376 |
376 // This test assumes that the above was sufficient to let the thread fully | 377 // This test assumes that the above was sufficient to let the thread fully |
(...skipping 15 matching lines...) Expand all Loading... |
392 Thread a("ThreadId0"); | 393 Thread a("ThreadId0"); |
393 Thread b("ThreadId1"); | 394 Thread b("ThreadId1"); |
394 a.Start(); | 395 a.Start(); |
395 b.Start(); | 396 b.Start(); |
396 | 397 |
397 // Post a task that calls GetThreadId() on the created thread. | 398 // Post a task that calls GetThreadId() on the created thread. |
398 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, | 399 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
399 base::WaitableEvent::InitialState::NOT_SIGNALED); | 400 base::WaitableEvent::InitialState::NOT_SIGNALED); |
400 base::PlatformThreadId id_from_new_thread; | 401 base::PlatformThreadId id_from_new_thread; |
401 a.task_runner()->PostTask( | 402 a.task_runner()->PostTask( |
402 FROM_HERE, base::Bind(ReturnThreadId, &a, &id_from_new_thread, &event)); | 403 FROM_HERE, |
| 404 base::BindOnce(ReturnThreadId, &a, &id_from_new_thread, &event)); |
403 | 405 |
404 // Call GetThreadId() on the current thread before calling event.Wait() so | 406 // Call GetThreadId() on the current thread before calling event.Wait() so |
405 // that this test can find a race issue with TSAN. | 407 // that this test can find a race issue with TSAN. |
406 base::PlatformThreadId id_from_current_thread = a.GetThreadId(); | 408 base::PlatformThreadId id_from_current_thread = a.GetThreadId(); |
407 | 409 |
408 // Check if GetThreadId() returns consistent value in both threads. | 410 // Check if GetThreadId() returns consistent value in both threads. |
409 event.Wait(); | 411 event.Wait(); |
410 EXPECT_EQ(id_from_current_thread, id_from_new_thread); | 412 EXPECT_EQ(id_from_current_thread, id_from_new_thread); |
411 | 413 |
412 // A started thread should have a valid ID. | 414 // A started thread should have a valid ID. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 { | 453 { |
452 // Start a thread which writes its event into |captured_events|. | 454 // Start a thread which writes its event into |captured_events|. |
453 CaptureToEventList t(&captured_events); | 455 CaptureToEventList t(&captured_events); |
454 EXPECT_TRUE(t.Start()); | 456 EXPECT_TRUE(t.Start()); |
455 EXPECT_TRUE(t.message_loop()); | 457 EXPECT_TRUE(t.message_loop()); |
456 EXPECT_TRUE(t.IsRunning()); | 458 EXPECT_TRUE(t.IsRunning()); |
457 | 459 |
458 // Register an observer that writes into |captured_events| once the | 460 // Register an observer that writes into |captured_events| once the |
459 // thread's message loop is destroyed. | 461 // thread's message loop is destroyed. |
460 t.task_runner()->PostTask( | 462 t.task_runner()->PostTask( |
461 FROM_HERE, base::Bind(&RegisterDestructionObserver, | 463 FROM_HERE, |
462 base::Unretained(&loop_destruction_observer))); | 464 base::BindOnce(&RegisterDestructionObserver, |
| 465 base::Unretained(&loop_destruction_observer))); |
463 | 466 |
464 // Upon leaving this scope, the thread is deleted. | 467 // Upon leaving this scope, the thread is deleted. |
465 } | 468 } |
466 | 469 |
467 // Check the order of events during shutdown. | 470 // Check the order of events during shutdown. |
468 ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size()); | 471 ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size()); |
469 EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]); | 472 EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]); |
470 EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]); | 473 EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]); |
471 EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]); | 474 EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]); |
472 } | 475 } |
(...skipping 23 matching lines...) Expand all Loading... |
496 a.FlushForTesting(); | 499 a.FlushForTesting(); |
497 | 500 |
498 constexpr base::TimeDelta kSleepPerTestTask = | 501 constexpr base::TimeDelta kSleepPerTestTask = |
499 base::TimeDelta::FromMilliseconds(50); | 502 base::TimeDelta::FromMilliseconds(50); |
500 constexpr size_t kNumSleepTasks = 5; | 503 constexpr size_t kNumSleepTasks = 5; |
501 | 504 |
502 const base::TimeTicks ticks_before_post = base::TimeTicks::Now(); | 505 const base::TimeTicks ticks_before_post = base::TimeTicks::Now(); |
503 | 506 |
504 for (size_t i = 0; i < kNumSleepTasks; ++i) { | 507 for (size_t i = 0; i < kNumSleepTasks; ++i) { |
505 a.task_runner()->PostTask( | 508 a.task_runner()->PostTask( |
506 FROM_HERE, base::Bind(&base::PlatformThread::Sleep, kSleepPerTestTask)); | 509 FROM_HERE, |
| 510 base::BindOnce(&base::PlatformThread::Sleep, kSleepPerTestTask)); |
507 } | 511 } |
508 | 512 |
509 // All tasks should have executed, as reflected by the elapsed time. | 513 // All tasks should have executed, as reflected by the elapsed time. |
510 a.FlushForTesting(); | 514 a.FlushForTesting(); |
511 EXPECT_GE(base::TimeTicks::Now() - ticks_before_post, | 515 EXPECT_GE(base::TimeTicks::Now() - ticks_before_post, |
512 kNumSleepTasks * kSleepPerTestTask); | 516 kNumSleepTasks * kSleepPerTestTask); |
513 | 517 |
514 a.Stop(); | 518 a.Stop(); |
515 | 519 |
516 // Flushing a stopped thread should be a no-op. | 520 // Flushing a stopped thread should be a no-op. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 EXPECT_FALSE(a.IsRunning()); | 554 EXPECT_FALSE(a.IsRunning()); |
551 a.VerifyUsingExternalMessageLoop(false); | 555 a.VerifyUsingExternalMessageLoop(false); |
552 | 556 |
553 a.InstallMessageLoop(); | 557 a.InstallMessageLoop(); |
554 EXPECT_TRUE(a.message_loop()); | 558 EXPECT_TRUE(a.message_loop()); |
555 EXPECT_TRUE(a.IsRunning()); | 559 EXPECT_TRUE(a.IsRunning()); |
556 a.VerifyUsingExternalMessageLoop(true); | 560 a.VerifyUsingExternalMessageLoop(true); |
557 | 561 |
558 bool ran = false; | 562 bool ran = false; |
559 a.task_runner()->PostTask( | 563 a.task_runner()->PostTask( |
560 FROM_HERE, base::Bind([](bool* toggled) { *toggled = true; }, &ran)); | 564 FROM_HERE, base::BindOnce([](bool* toggled) { *toggled = true; }, &ran)); |
561 base::RunLoop().RunUntilIdle(); | 565 base::RunLoop().RunUntilIdle(); |
562 EXPECT_TRUE(ran); | 566 EXPECT_TRUE(ran); |
563 | 567 |
564 a.Stop(); | 568 a.Stop(); |
565 EXPECT_FALSE(a.message_loop()); | 569 EXPECT_FALSE(a.message_loop()); |
566 EXPECT_FALSE(a.IsRunning()); | 570 EXPECT_FALSE(a.IsRunning()); |
567 a.VerifyUsingExternalMessageLoop(true); | 571 a.VerifyUsingExternalMessageLoop(true); |
568 | 572 |
569 // Confirm that running any remaining tasks posted from Stop() goes smoothly | 573 // Confirm that running any remaining tasks posted from Stop() goes smoothly |
570 // (e.g. https://codereview.chromium.org/2135413003/#ps300001 crashed if | 574 // (e.g. https://codereview.chromium.org/2135413003/#ps300001 crashed if |
571 // StopSoon() posted Thread::ThreadQuitHelper() while |run_loop_| was null). | 575 // StopSoon() posted Thread::ThreadQuitHelper() while |run_loop_| was null). |
572 base::RunLoop().RunUntilIdle(); | 576 base::RunLoop().RunUntilIdle(); |
573 } | 577 } |
OLD | NEW |