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

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

Issue 1439613004: Fix a data race in the thread unit tests. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Addressed final(?) nits. Created 5 years, 1 month 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 | « no previous file | 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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 } 130 }
131 131
132 virtual void Run() { 132 virtual void Run() {
133 // Do nothing. 133 // Do nothing.
134 } 134 }
135 135
136 private: 136 private:
137 Event* event_; 137 Event* event_;
138 }; 138 };
139 139
140 // A bool wrapped in a mutex, to avoid data races. Using a volatile
141 // bool should be sufficient for correct code ("eventual consistency"
142 // between caches is sufficient), but we can't tell the compiler about
143 // that, and then tsan complains about a data race.
144
145 // See also discussion at
146 // http://stackoverflow.com/questions/7223164/is-mutex-needed-to-synchronize-a-s imple-flag-between-pthreads
147
148 // Using std::atomic<bool> or std::atomic_flag in C++11 is probably
149 // the right thing to do, but those features are not yet allowed. Or
150 // rtc::AtomicInt, if/when that is added. Since the use isn't
151 // performance critical, use a plain critical section for the time
152 // being.
153
154 class AtomicBool {
155 public:
156 explicit AtomicBool(bool value = false) : flag_(value) {}
157 AtomicBool& operator=(bool value) {
158 CritScope scoped_lock(&cs_);
159 flag_ = value;
160 return *this;
161 }
162 bool get() const {
163 CritScope scoped_lock(&cs_);
164 return flag_;
165 }
166
167 private:
168 mutable CriticalSection cs_;
169 bool flag_;
170 };
171
140 // Function objects to test Thread::Invoke. 172 // Function objects to test Thread::Invoke.
141 struct FunctorA { 173 struct FunctorA {
142 int operator()() { return 42; } 174 int operator()() { return 42; }
143 }; 175 };
144 class FunctorB { 176 class FunctorB {
145 public: 177 public:
146 explicit FunctorB(bool* flag) : flag_(flag) {} 178 explicit FunctorB(AtomicBool* flag) : flag_(flag) {}
147 void operator()() { if (flag_) *flag_ = true; } 179 void operator()() { if (flag_) *flag_ = true; }
148 private: 180 private:
149 bool* flag_; 181 AtomicBool* flag_;
150 }; 182 };
151 struct FunctorC { 183 struct FunctorC {
152 int operator()() { 184 int operator()() {
153 Thread::Current()->ProcessMessages(50); 185 Thread::Current()->ProcessMessages(50);
154 return 24; 186 return 24;
155 } 187 }
156 }; 188 };
157 189
158 // See: https://code.google.com/p/webrtc/issues/detail?id=2409 190 // See: https://code.google.com/p/webrtc/issues/detail?id=2409
159 TEST(ThreadTest, DISABLED_Main) { 191 TEST(ThreadTest, DISABLED_Main) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 delete cthread; 291 delete cthread;
260 current_thread->WrapCurrent(); 292 current_thread->WrapCurrent();
261 } 293 }
262 294
263 TEST(ThreadTest, Invoke) { 295 TEST(ThreadTest, Invoke) {
264 // Create and start the thread. 296 // Create and start the thread.
265 Thread thread; 297 Thread thread;
266 thread.Start(); 298 thread.Start();
267 // Try calling functors. 299 // Try calling functors.
268 EXPECT_EQ(42, thread.Invoke<int>(FunctorA())); 300 EXPECT_EQ(42, thread.Invoke<int>(FunctorA()));
269 bool called = false; 301 AtomicBool called;
270 FunctorB f2(&called); 302 FunctorB f2(&called);
271 thread.Invoke<void>(f2); 303 thread.Invoke<void>(f2);
272 EXPECT_TRUE(called); 304 EXPECT_TRUE(called.get());
273 // Try calling bare functions. 305 // Try calling bare functions.
274 struct LocalFuncs { 306 struct LocalFuncs {
275 static int Func1() { return 999; } 307 static int Func1() { return 999; }
276 static void Func2() {} 308 static void Func2() {}
277 }; 309 };
278 EXPECT_EQ(999, thread.Invoke<int>(&LocalFuncs::Func1)); 310 EXPECT_EQ(999, thread.Invoke<int>(&LocalFuncs::Func1));
279 thread.Invoke<void>(&LocalFuncs::Func2); 311 thread.Invoke<void>(&LocalFuncs::Func2);
280 } 312 }
281 313
282 // Verifies that two threads calling Invoke on each other at the same time does 314 // Verifies that two threads calling Invoke on each other at the same time does
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 Event invoke_started_; 433 Event invoke_started_;
402 Thread* expected_thread_; 434 Thread* expected_thread_;
403 }; 435 };
404 436
405 TEST_F(AsyncInvokeTest, FireAndForget) { 437 TEST_F(AsyncInvokeTest, FireAndForget) {
406 AsyncInvoker invoker; 438 AsyncInvoker invoker;
407 // Create and start the thread. 439 // Create and start the thread.
408 Thread thread; 440 Thread thread;
409 thread.Start(); 441 thread.Start();
410 // Try calling functor. 442 // Try calling functor.
411 bool called = false; 443 AtomicBool called;
412 invoker.AsyncInvoke<void>(&thread, FunctorB(&called)); 444 invoker.AsyncInvoke<void>(&thread, FunctorB(&called));
413 EXPECT_TRUE_WAIT(called, kWaitTimeout); 445 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
414 } 446 }
415 447
416 TEST_F(AsyncInvokeTest, WithCallback) { 448 TEST_F(AsyncInvokeTest, WithCallback) {
417 AsyncInvoker invoker; 449 AsyncInvoker invoker;
418 // Create and start the thread. 450 // Create and start the thread.
419 Thread thread; 451 Thread thread;
420 thread.Start(); 452 thread.Start();
421 // Try calling functor. 453 // Try calling functor.
422 SetExpectedThreadForIntCallback(Thread::Current()); 454 SetExpectedThreadForIntCallback(Thread::Current());
423 invoker.AsyncInvoke(&thread, FunctorA(), 455 invoker.AsyncInvoke(&thread, FunctorA(),
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 // Wait for the call to begin. 503 // Wait for the call to begin.
472 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); 504 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
473 } 505 }
474 // Invoker is destroyed. Function should not execute. 506 // Invoker is destroyed. Function should not execute.
475 Thread::Current()->ProcessMessages(kWaitTimeout); 507 Thread::Current()->ProcessMessages(kWaitTimeout);
476 EXPECT_EQ(0, int_value_); 508 EXPECT_EQ(0, int_value_);
477 } 509 }
478 510
479 TEST_F(AsyncInvokeTest, Flush) { 511 TEST_F(AsyncInvokeTest, Flush) {
480 AsyncInvoker invoker; 512 AsyncInvoker invoker;
481 bool flag1 = false; 513 AtomicBool flag1;
482 bool flag2 = false; 514 AtomicBool flag2;
483 // Queue two async calls to the current thread. 515 // Queue two async calls to the current thread.
484 invoker.AsyncInvoke<void>(Thread::Current(), 516 invoker.AsyncInvoke<void>(Thread::Current(),
485 FunctorB(&flag1)); 517 FunctorB(&flag1));
486 invoker.AsyncInvoke<void>(Thread::Current(), 518 invoker.AsyncInvoke<void>(Thread::Current(),
487 FunctorB(&flag2)); 519 FunctorB(&flag2));
488 // Because we haven't pumped messages, these should not have run yet. 520 // Because we haven't pumped messages, these should not have run yet.
489 EXPECT_FALSE(flag1); 521 EXPECT_FALSE(flag1.get());
490 EXPECT_FALSE(flag2); 522 EXPECT_FALSE(flag2.get());
491 // Force them to run now. 523 // Force them to run now.
492 invoker.Flush(Thread::Current()); 524 invoker.Flush(Thread::Current());
493 EXPECT_TRUE(flag1); 525 EXPECT_TRUE(flag1.get());
494 EXPECT_TRUE(flag2); 526 EXPECT_TRUE(flag2.get());
495 } 527 }
496 528
497 TEST_F(AsyncInvokeTest, FlushWithIds) { 529 TEST_F(AsyncInvokeTest, FlushWithIds) {
498 AsyncInvoker invoker; 530 AsyncInvoker invoker;
499 bool flag1 = false; 531 AtomicBool flag1;
500 bool flag2 = false; 532 AtomicBool flag2;
501 // Queue two async calls to the current thread, one with a message id. 533 // Queue two async calls to the current thread, one with a message id.
502 invoker.AsyncInvoke<void>(Thread::Current(), 534 invoker.AsyncInvoke<void>(Thread::Current(),
503 FunctorB(&flag1), 535 FunctorB(&flag1),
504 5); 536 5);
505 invoker.AsyncInvoke<void>(Thread::Current(), 537 invoker.AsyncInvoke<void>(Thread::Current(),
506 FunctorB(&flag2)); 538 FunctorB(&flag2));
507 // Because we haven't pumped messages, these should not have run yet. 539 // Because we haven't pumped messages, these should not have run yet.
508 EXPECT_FALSE(flag1); 540 EXPECT_FALSE(flag1.get());
509 EXPECT_FALSE(flag2); 541 EXPECT_FALSE(flag2.get());
510 // Execute pending calls with id == 5. 542 // Execute pending calls with id == 5.
511 invoker.Flush(Thread::Current(), 5); 543 invoker.Flush(Thread::Current(), 5);
512 EXPECT_TRUE(flag1); 544 EXPECT_TRUE(flag1.get());
513 EXPECT_FALSE(flag2); 545 EXPECT_FALSE(flag2.get());
514 flag1 = false; 546 flag1 = false;
515 // Execute all pending calls. The id == 5 call should not execute again. 547 // Execute all pending calls. The id == 5 call should not execute again.
516 invoker.Flush(Thread::Current()); 548 invoker.Flush(Thread::Current());
517 EXPECT_FALSE(flag1); 549 EXPECT_FALSE(flag1.get());
518 EXPECT_TRUE(flag2); 550 EXPECT_TRUE(flag2.get());
519 } 551 }
520 552
521 class GuardedAsyncInvokeTest : public testing::Test { 553 class GuardedAsyncInvokeTest : public testing::Test {
522 public: 554 public:
523 void IntCallback(int value) { 555 void IntCallback(int value) {
524 EXPECT_EQ(expected_thread_, Thread::Current()); 556 EXPECT_EQ(expected_thread_, Thread::Current());
525 int_value_ = value; 557 int_value_ = value;
526 } 558 }
527 void AsyncInvokeIntCallback(GuardedAsyncInvoker* invoker, Thread* thread) { 559 void AsyncInvokeIntCallback(GuardedAsyncInvoker* invoker, Thread* thread) {
528 expected_thread_ = thread; 560 expected_thread_ = thread;
(...skipping 28 matching lines...) Expand all
557 TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) { 589 TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) {
558 // Create and start the thread. 590 // Create and start the thread.
559 scoped_ptr<Thread> thread(new Thread()); 591 scoped_ptr<Thread> thread(new Thread());
560 thread->Start(); 592 thread->Start();
561 scoped_ptr<GuardedAsyncInvoker> invoker; 593 scoped_ptr<GuardedAsyncInvoker> invoker;
562 // Create the invoker on |thread|. 594 // Create the invoker on |thread|.
563 thread->Invoke<void>(CreateInvoker(&invoker)); 595 thread->Invoke<void>(CreateInvoker(&invoker));
564 // Kill |thread|. 596 // Kill |thread|.
565 thread = nullptr; 597 thread = nullptr;
566 // Try calling functor. 598 // Try calling functor.
567 bool called = false; 599 AtomicBool called;
568 EXPECT_FALSE(invoker->AsyncInvoke<void>(FunctorB(&called))); 600 EXPECT_FALSE(invoker->AsyncInvoke<void>(FunctorB(&called)));
569 // With thread gone, nothing should happen. 601 // With thread gone, nothing should happen.
570 WAIT(called, kWaitTimeout); 602 WAIT(called.get(), kWaitTimeout);
571 EXPECT_FALSE(called); 603 EXPECT_FALSE(called.get());
572 } 604 }
573 605
574 // Test that we can call AsyncInvoke with callback after the thread died. 606 // Test that we can call AsyncInvoke with callback after the thread died.
575 TEST_F(GuardedAsyncInvokeTest, KillThreadWithCallback) { 607 TEST_F(GuardedAsyncInvokeTest, KillThreadWithCallback) {
576 // Create and start the thread. 608 // Create and start the thread.
577 scoped_ptr<Thread> thread(new Thread()); 609 scoped_ptr<Thread> thread(new Thread());
578 thread->Start(); 610 thread->Start();
579 scoped_ptr<GuardedAsyncInvoker> invoker; 611 scoped_ptr<GuardedAsyncInvoker> invoker;
580 // Create the invoker on |thread|. 612 // Create the invoker on |thread|.
581 thread->Invoke<void>(CreateInvoker(&invoker)); 613 thread->Invoke<void>(CreateInvoker(&invoker));
582 // Kill |thread|. 614 // Kill |thread|.
583 thread = nullptr; 615 thread = nullptr;
584 // Try calling functor. 616 // Try calling functor.
585 EXPECT_FALSE( 617 EXPECT_FALSE(
586 invoker->AsyncInvoke(FunctorC(), &GuardedAsyncInvokeTest::IntCallback, 618 invoker->AsyncInvoke(FunctorC(), &GuardedAsyncInvokeTest::IntCallback,
587 static_cast<GuardedAsyncInvokeTest*>(this))); 619 static_cast<GuardedAsyncInvokeTest*>(this)));
588 // With thread gone, callback should be cancelled. 620 // With thread gone, callback should be cancelled.
589 Thread::Current()->ProcessMessages(kWaitTimeout); 621 Thread::Current()->ProcessMessages(kWaitTimeout);
590 EXPECT_EQ(0, int_value_); 622 EXPECT_EQ(0, int_value_);
591 } 623 }
592 624
593 // The remaining tests check that GuardedAsyncInvoker behaves as AsyncInvoker 625 // The remaining tests check that GuardedAsyncInvoker behaves as AsyncInvoker
594 // when Thread is still alive. 626 // when Thread is still alive.
595 TEST_F(GuardedAsyncInvokeTest, FireAndForget) { 627 TEST_F(GuardedAsyncInvokeTest, FireAndForget) {
596 GuardedAsyncInvoker invoker; 628 GuardedAsyncInvoker invoker;
597 // Try calling functor. 629 // Try calling functor.
598 bool called = false; 630 AtomicBool called;
599 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&called))); 631 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&called)));
600 EXPECT_TRUE_WAIT(called, kWaitTimeout); 632 EXPECT_TRUE_WAIT(called.get(), kWaitTimeout);
601 } 633 }
602 634
603 TEST_F(GuardedAsyncInvokeTest, WithCallback) { 635 TEST_F(GuardedAsyncInvokeTest, WithCallback) {
604 GuardedAsyncInvoker invoker; 636 GuardedAsyncInvoker invoker;
605 // Try calling functor. 637 // Try calling functor.
606 SetExpectedThreadForIntCallback(Thread::Current()); 638 SetExpectedThreadForIntCallback(Thread::Current());
607 EXPECT_TRUE(invoker.AsyncInvoke(FunctorA(), 639 EXPECT_TRUE(invoker.AsyncInvoke(FunctorA(),
608 &GuardedAsyncInvokeTest::IntCallback, 640 &GuardedAsyncInvokeTest::IntCallback,
609 static_cast<GuardedAsyncInvokeTest*>(this))); 641 static_cast<GuardedAsyncInvokeTest*>(this)));
610 EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout); 642 EXPECT_EQ_WAIT(42, int_value_, kWaitTimeout);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 // Wait for the call to begin. 685 // Wait for the call to begin.
654 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); 686 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout));
655 } 687 }
656 // Invoker is destroyed. Function should not execute. 688 // Invoker is destroyed. Function should not execute.
657 Thread::Current()->ProcessMessages(kWaitTimeout); 689 Thread::Current()->ProcessMessages(kWaitTimeout);
658 EXPECT_EQ(0, int_value_); 690 EXPECT_EQ(0, int_value_);
659 } 691 }
660 692
661 TEST_F(GuardedAsyncInvokeTest, Flush) { 693 TEST_F(GuardedAsyncInvokeTest, Flush) {
662 GuardedAsyncInvoker invoker; 694 GuardedAsyncInvoker invoker;
663 bool flag1 = false; 695 AtomicBool flag1;
664 bool flag2 = false; 696 AtomicBool flag2;
665 // Queue two async calls to the current thread. 697 // Queue two async calls to the current thread.
666 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1))); 698 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1)));
667 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2))); 699 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2)));
668 // Because we haven't pumped messages, these should not have run yet. 700 // Because we haven't pumped messages, these should not have run yet.
669 EXPECT_FALSE(flag1); 701 EXPECT_FALSE(flag1.get());
670 EXPECT_FALSE(flag2); 702 EXPECT_FALSE(flag2.get());
671 // Force them to run now. 703 // Force them to run now.
672 EXPECT_TRUE(invoker.Flush()); 704 EXPECT_TRUE(invoker.Flush());
673 EXPECT_TRUE(flag1); 705 EXPECT_TRUE(flag1.get());
674 EXPECT_TRUE(flag2); 706 EXPECT_TRUE(flag2.get());
675 } 707 }
676 708
677 TEST_F(GuardedAsyncInvokeTest, FlushWithIds) { 709 TEST_F(GuardedAsyncInvokeTest, FlushWithIds) {
678 GuardedAsyncInvoker invoker; 710 GuardedAsyncInvoker invoker;
679 bool flag1 = false; 711 AtomicBool flag1;
680 bool flag2 = false; 712 AtomicBool flag2;
681 // Queue two async calls to the current thread, one with a message id. 713 // Queue two async calls to the current thread, one with a message id.
682 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1), 5)); 714 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1), 5));
683 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2))); 715 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2)));
684 // Because we haven't pumped messages, these should not have run yet. 716 // Because we haven't pumped messages, these should not have run yet.
685 EXPECT_FALSE(flag1); 717 EXPECT_FALSE(flag1.get());
686 EXPECT_FALSE(flag2); 718 EXPECT_FALSE(flag2.get());
687 // Execute pending calls with id == 5. 719 // Execute pending calls with id == 5.
688 EXPECT_TRUE(invoker.Flush(5)); 720 EXPECT_TRUE(invoker.Flush(5));
689 EXPECT_TRUE(flag1); 721 EXPECT_TRUE(flag1.get());
690 EXPECT_FALSE(flag2); 722 EXPECT_FALSE(flag2.get());
691 flag1 = false; 723 flag1 = false;
692 // Execute all pending calls. The id == 5 call should not execute again. 724 // Execute all pending calls. The id == 5 call should not execute again.
693 EXPECT_TRUE(invoker.Flush()); 725 EXPECT_TRUE(invoker.Flush());
694 EXPECT_FALSE(flag1); 726 EXPECT_FALSE(flag1.get());
695 EXPECT_TRUE(flag2); 727 EXPECT_TRUE(flag2.get());
696 } 728 }
697 729
698 #if defined(WEBRTC_WIN) 730 #if defined(WEBRTC_WIN)
699 class ComThreadTest : public testing::Test, public MessageHandler { 731 class ComThreadTest : public testing::Test, public MessageHandler {
700 public: 732 public:
701 ComThreadTest() : done_(false) {} 733 ComThreadTest() : done_(false) {}
702 protected: 734 protected:
703 virtual void OnMessage(Message* message) { 735 virtual void OnMessage(Message* message) {
704 HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 736 HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
705 // S_FALSE means the thread was already inited for a multithread apartment. 737 // S_FALSE means the thread was already inited for a multithread apartment.
706 EXPECT_EQ(S_FALSE, hr); 738 EXPECT_EQ(S_FALSE, hr);
707 if (SUCCEEDED(hr)) { 739 if (SUCCEEDED(hr)) {
708 CoUninitialize(); 740 CoUninitialize();
709 } 741 }
710 done_ = true; 742 done_ = true;
711 } 743 }
712 bool done_; 744 bool done_;
713 }; 745 };
714 746
715 TEST_F(ComThreadTest, ComInited) { 747 TEST_F(ComThreadTest, ComInited) {
716 Thread* thread = new ComThread(); 748 Thread* thread = new ComThread();
717 EXPECT_TRUE(thread->Start()); 749 EXPECT_TRUE(thread->Start());
718 thread->Post(this, 0); 750 thread->Post(this, 0);
719 EXPECT_TRUE_WAIT(done_, 1000); 751 EXPECT_TRUE_WAIT(done_, 1000);
720 delete thread; 752 delete thread;
721 } 753 }
722 #endif 754 #endif
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698