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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 AtomicFlag { | |
tommi
2015/11/13 14:22:23
AtomicBool
nisse-webrtc
2015/11/13 15:07:12
Done.
| |
155 public: | |
156 explicit AtomicFlag(bool value = false) : flag_(value) {} | |
157 AtomicFlag& operator=(bool value) { | |
158 CritScope scoped_lock(&cs_); | |
159 flag_ = value; | |
160 return *this; | |
161 } | |
162 operator bool() const { | |
tommi
2015/11/13 14:22:24
bool get_value() const {
nisse-webrtc
2015/11/13 15:07:12
Done. (But with the shorter name get()).
| |
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(AtomicFlag* 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 AtomicFlag* 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 Loading... | |
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 AtomicFlag 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); |
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); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 AtomicFlag 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, 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. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 AtomicFlag flag1; |
482 bool flag2 = false; | 514 AtomicFlag 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); |
490 EXPECT_FALSE(flag2); | 522 EXPECT_FALSE(flag2); |
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); |
494 EXPECT_TRUE(flag2); | 526 EXPECT_TRUE(flag2); |
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 AtomicFlag flag1; |
500 bool flag2 = false; | 532 AtomicFlag 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); |
509 EXPECT_FALSE(flag2); | 541 EXPECT_FALSE(flag2); |
510 // Execute pending calls with id == 5. | 542 // Execute pending calls with id == 5. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 AtomicFlag 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, kWaitTimeout); |
571 EXPECT_FALSE(called); | 603 EXPECT_FALSE(called); |
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()); |
(...skipping 10 matching lines...) Expand all Loading... | |
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 AtomicFlag 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, 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, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 AtomicFlag flag1; |
664 bool flag2 = false; | 696 AtomicFlag 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); |
670 EXPECT_FALSE(flag2); | 702 EXPECT_FALSE(flag2); |
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); |
674 EXPECT_TRUE(flag2); | 706 EXPECT_TRUE(flag2); |
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 AtomicFlag flag1; |
680 bool flag2 = false; | 712 AtomicFlag 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); |
686 EXPECT_FALSE(flag2); | 718 EXPECT_FALSE(flag2); |
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); |
690 EXPECT_FALSE(flag2); | 722 EXPECT_FALSE(flag2); |
(...skipping 22 matching lines...) Expand all Loading... | |
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 |
OLD | NEW |