Index: webrtc/base/thread_unittest.cc |
diff --git a/webrtc/base/thread_unittest.cc b/webrtc/base/thread_unittest.cc |
index b0c8cb59af952a3f7afea26702d758934987bdac..e4e74d6db00a662241c24096b52ba3daa137c499 100644 |
--- a/webrtc/base/thread_unittest.cc |
+++ b/webrtc/base/thread_unittest.cc |
@@ -356,13 +356,14 @@ TEST(ThreadTest, ThreeThreadsInvoke) { |
// Asynchronously invoke SetAndInvokeSet on |thread1| and wait until |
// |thread1| starts the call. |
- static void AsyncInvokeSetAndWait( |
- Thread* thread1, Thread* thread2, LockedBool* out) { |
+ static void AsyncInvokeSetAndWait(AsyncInvoker* invoker, |
+ Thread* thread1, |
+ Thread* thread2, |
+ LockedBool* out) { |
CriticalSection crit; |
LockedBool async_invoked(false); |
- AsyncInvoker invoker; |
- invoker.AsyncInvoke<void>( |
+ invoker->AsyncInvoke<void>( |
RTC_FROM_HERE, thread1, |
Bind(&SetAndInvokeSet, &async_invoked, thread2, out)); |
@@ -370,14 +371,15 @@ TEST(ThreadTest, ThreeThreadsInvoke) { |
} |
}; |
+ AsyncInvoker invoker; |
LockedBool thread_a_called(false); |
// Start the sequence A --(invoke)--> B --(async invoke)--> C --(invoke)--> A. |
// Thread B returns when C receives the call and C should be blocked until A |
// starts to process messages. |
thread_b.Invoke<void>(RTC_FROM_HERE, |
- Bind(&LocalFuncs::AsyncInvokeSetAndWait, &thread_c, |
- thread_a, &thread_a_called)); |
+ Bind(&LocalFuncs::AsyncInvokeSetAndWait, &invoker, |
+ &thread_c, thread_a, &thread_a_called)); |
EXPECT_FALSE(thread_a_called.Get()); |
EXPECT_TRUE_WAIT(thread_a_called.Get(), 2000); |
@@ -524,6 +526,41 @@ TEST_F(AsyncInvokeTest, KillInvokerBeforeExecute) { |
EXPECT_EQ(0, int_value_); |
} |
+TEST_F(AsyncInvokeTest, KillInvokerDuringExecute) { |
+ // Use these events to get in a state where the functor is in the middle of |
+ // executing, and then to wait for it to finish, ensuring the "EXPECT_FALSE" |
+ // is run. |
+ Event functor_started(false, false); |
+ Event functor_continue(false, false); |
+ Event functor_finished(false, false); |
+ |
+ Thread thread; |
+ thread.Start(); |
+ volatile bool invoker_destroyed = false; |
+ { |
+ AsyncInvoker invoker; |
+ invoker.AsyncInvoke<void>(RTC_FROM_HERE, &thread, |
+ [&functor_started, &functor_continue, |
+ &functor_finished, &invoker_destroyed] { |
+ functor_started.Set(); |
+ functor_continue.Wait(Event::kForever); |
+ rtc::Thread::Current()->SleepMs(kWaitTimeout); |
+ EXPECT_FALSE(invoker_destroyed); |
+ functor_finished.Set(); |
+ }); |
+ functor_started.Wait(Event::kForever); |
+ |
+ // Allow the functor to continue and immediately destroy the invoker. |
+ functor_continue.Set(); |
+ } |
+ |
+ // If the destructor DIDN'T wait for the functor to finish executing, it will |
+ // hit the EXPECT_FALSE(invoker_destroyed) after it finishes sleeping for a |
+ // second. |
+ invoker_destroyed = true; |
+ functor_finished.Wait(Event::kForever); |
+} |
+ |
TEST_F(AsyncInvokeTest, Flush) { |
AsyncInvoker invoker; |
AtomicBool flag1; |