| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 // Set |out| true and call InvokeSet on |thread|. | 349 // Set |out| true and call InvokeSet on |thread|. |
| 350 static void SetAndInvokeSet(LockedBool* out, | 350 static void SetAndInvokeSet(LockedBool* out, |
| 351 Thread* thread, | 351 Thread* thread, |
| 352 LockedBool* out_inner) { | 352 LockedBool* out_inner) { |
| 353 out->Set(true); | 353 out->Set(true); |
| 354 InvokeSet(thread, out_inner); | 354 InvokeSet(thread, out_inner); |
| 355 } | 355 } |
| 356 | 356 |
| 357 // Asynchronously invoke SetAndInvokeSet on |thread1| and wait until | 357 // Asynchronously invoke SetAndInvokeSet on |thread1| and wait until |
| 358 // |thread1| starts the call. | 358 // |thread1| starts the call. |
| 359 static void AsyncInvokeSetAndWait( | 359 static void AsyncInvokeSetAndWait(AsyncInvoker* invoker, |
| 360 Thread* thread1, Thread* thread2, LockedBool* out) { | 360 Thread* thread1, |
| 361 Thread* thread2, |
| 362 LockedBool* out) { |
| 361 CriticalSection crit; | 363 CriticalSection crit; |
| 362 LockedBool async_invoked(false); | 364 LockedBool async_invoked(false); |
| 363 | 365 |
| 364 AsyncInvoker invoker; | 366 invoker->AsyncInvoke<void>( |
| 365 invoker.AsyncInvoke<void>( | |
| 366 RTC_FROM_HERE, thread1, | 367 RTC_FROM_HERE, thread1, |
| 367 Bind(&SetAndInvokeSet, &async_invoked, thread2, out)); | 368 Bind(&SetAndInvokeSet, &async_invoked, thread2, out)); |
| 368 | 369 |
| 369 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000); | 370 EXPECT_TRUE_WAIT(async_invoked.Get(), 2000); |
| 370 } | 371 } |
| 371 }; | 372 }; |
| 372 | 373 |
| 374 AsyncInvoker invoker; |
| 373 LockedBool thread_a_called(false); | 375 LockedBool thread_a_called(false); |
| 374 | 376 |
| 375 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A. | 377 // Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A. |
| 376 // Thread B returns when C receives the call and C should be blocked until A | 378 // Thread B returns when C receives the call and C should be blocked until A |
| 377 // starts to process messages. | 379 // starts to process messages. |
| 378 thread_b.Invoke<void>(RTC_FROM_HERE, | 380 thread_b.Invoke<void>(RTC_FROM_HERE, |
| 379 Bind(&LocalFuncs::AsyncInvokeSetAndWait, &thread_c, | 381 Bind(&LocalFuncs::AsyncInvokeSetAndWait, &invoker, |
| 380 thread_a, &thread_a_called)); | 382 &thread_c, thread_a, &thread_a_called)); |
| 381 EXPECT_FALSE(thread_a_called.Get()); | 383 EXPECT_FALSE(thread_a_called.Get()); |
| 382 | 384 |
| 383 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000); | 385 EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000); |
| 384 } | 386 } |
| 385 | 387 |
| 386 // Set the name on a thread when the underlying QueueDestroyed signal is | 388 // Set the name on a thread when the underlying QueueDestroyed signal is |
| 387 // triggered. This causes an error if the object is already partially | 389 // triggered. This causes an error if the object is already partially |
| 388 // destroyed. | 390 // destroyed. |
| 389 class SetNameOnSignalQueueDestroyedTester : public sigslot::has_slots<> { | 391 class SetNameOnSignalQueueDestroyedTester : public sigslot::has_slots<> { |
| 390 public: | 392 public: |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 Bind(&AsyncInvokeTest::AsyncInvokeIntCallback, | 519 Bind(&AsyncInvokeTest::AsyncInvokeIntCallback, |
| 518 static_cast<AsyncInvokeTest*>(this), &invoker, Thread::Current())); | 520 static_cast<AsyncInvokeTest*>(this), &invoker, Thread::Current())); |
| 519 // Wait for the call to begin. | 521 // Wait for the call to begin. |
| 520 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); | 522 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); |
| 521 } | 523 } |
| 522 // Invoker is destroyed. Function should not execute. | 524 // Invoker is destroyed. Function should not execute. |
| 523 Thread::Current()->ProcessMessages(kWaitTimeout); | 525 Thread::Current()->ProcessMessages(kWaitTimeout); |
| 524 EXPECT_EQ(0, int_value_); | 526 EXPECT_EQ(0, int_value_); |
| 525 } | 527 } |
| 526 | 528 |
| 529 TEST_F(AsyncInvokeTest, KillInvokerDuringExecute) { |
| 530 // Use these events to get in a state where the functor is in the middle of |
| 531 // executing, and then to wait for it to finish, ensuring the "EXPECT_FALSE" |
| 532 // is run. |
| 533 Event functor_started(false, false); |
| 534 Event functor_continue(false, false); |
| 535 Event functor_finished(false, false); |
| 536 |
| 537 Thread thread; |
| 538 thread.Start(); |
| 539 volatile bool invoker_destroyed = false; |
| 540 { |
| 541 AsyncInvoker invoker; |
| 542 invoker.AsyncInvoke<void>(RTC_FROM_HERE, &thread, |
| 543 [&functor_started, &functor_continue, |
| 544 &functor_finished, &invoker_destroyed] { |
| 545 functor_started.Set(); |
| 546 functor_continue.Wait(Event::kForever); |
| 547 rtc::Thread::Current()->SleepMs(kWaitTimeout); |
| 548 EXPECT_FALSE(invoker_destroyed); |
| 549 functor_finished.Set(); |
| 550 }); |
| 551 functor_started.Wait(Event::kForever); |
| 552 |
| 553 // Allow the functor to continue and immediately destroy the invoker. |
| 554 functor_continue.Set(); |
| 555 } |
| 556 |
| 557 // If the destructor DIDN'T wait for the functor to finish executing, it will |
| 558 // hit the EXPECT_FALSE(invoker_destroyed) after it finishes sleeping for a |
| 559 // second. |
| 560 invoker_destroyed = true; |
| 561 functor_finished.Wait(Event::kForever); |
| 562 } |
| 563 |
| 527 TEST_F(AsyncInvokeTest, Flush) { | 564 TEST_F(AsyncInvokeTest, Flush) { |
| 528 AsyncInvoker invoker; | 565 AsyncInvoker invoker; |
| 529 AtomicBool flag1; | 566 AtomicBool flag1; |
| 530 AtomicBool flag2; | 567 AtomicBool flag2; |
| 531 // Queue two async calls to the current thread. | 568 // Queue two async calls to the current thread. |
| 532 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1)); | 569 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1)); |
| 533 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2)); | 570 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2)); |
| 534 // Because we haven't pumped messages, these should not have run yet. | 571 // Because we haven't pumped messages, these should not have run yet. |
| 535 EXPECT_FALSE(flag1.get()); | 572 EXPECT_FALSE(flag1.get()); |
| 536 EXPECT_FALSE(flag2.get()); | 573 EXPECT_FALSE(flag2.get()); |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 763 }; | 800 }; |
| 764 | 801 |
| 765 TEST_F(ComThreadTest, ComInited) { | 802 TEST_F(ComThreadTest, ComInited) { |
| 766 Thread* thread = new ComThread(); | 803 Thread* thread = new ComThread(); |
| 767 EXPECT_TRUE(thread->Start()); | 804 EXPECT_TRUE(thread->Start()); |
| 768 thread->Post(RTC_FROM_HERE, this, 0); | 805 thread->Post(RTC_FROM_HERE, this, 0); |
| 769 EXPECT_TRUE_WAIT(done_, 1000); | 806 EXPECT_TRUE_WAIT(done_, 1000); |
| 770 delete thread; | 807 delete thread; |
| 771 } | 808 } |
| 772 #endif | 809 #endif |
| OLD | NEW |