| 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 |