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); | |
pthatcher1
2017/02/17 18:19:38
Nice unit test
| |
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 |