Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Side by Side Diff: webrtc/base/thread_unittest.cc

Issue 2694723004: Making AsyncInvoker destructor thread-safe. (Closed)
Patch Set: Merge with master Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/base/event.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « webrtc/base/event.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698