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, do 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. | |
150 // Since the use isn't performance critical, use a plain mutex for the | |
151 // time being. | |
152 | |
153 class AtomicFlag | |
154 { | |
magjed_webrtc
2015/11/11 15:50:44
You are not following the C++ style guide. The Web
nisse-webrtc
2015/11/12 08:39:05
Done. I've also added a google style in my emacs c
magjed_webrtc
2015/11/12 09:20:51
You can also take a look at go/emacs.
| |
155 public: | |
156 AtomicFlag(bool value) : flag(value) {} | |
magjed_webrtc
2015/11/11 15:50:44
I'm not sure you are allowed to use implicit conve
nisse-webrtc
2015/11/12 08:39:05
I can make it explicit. Only reason for implicit w
tommi
2015/11/12 08:49:52
Adding a default ctor that initializes to false ma
magjed_webrtc
2015/11/12 09:20:51
FYI - Here is a link to the style guide:
"Do not d
nisse-webrtc
2015/11/12 09:58:23
I changed the constructor to explicit (and with a
nisse-webrtc
2015/11/12 09:58:23
Done.
tommi
2015/11/12 10:16:31
hah! Yeah, well, maybe the class could be called
magjed_webrtc
2015/11/12 11:04:38
Yes, you should probably make the conversion to bo
| |
157 bool operator= (bool value) { | |
nisse-webrtc
2015/11/12 08:39:05
What's the proper return type for this assignment
tommi
2015/11/12 08:49:52
yes, return a reference to *this.
magjed_webrtc
2015/11/12 09:20:51
The typical copy assignment operator would take th
nisse-webrtc
2015/11/12 09:58:23
Done.
| |
158 cs.Enter(); | |
magjed_webrtc
2015/11/11 15:50:44
Instead of manual Enter() and Leave(), you can use
nisse-webrtc
2015/11/12 08:39:05
Done.
| |
159 flag = value; | |
160 cs.Leave(); | |
161 return value; | |
162 } | |
163 operator bool() const { | |
164 bool value; | |
165 cs.Enter(); | |
166 value = flag; | |
167 cs.Leave(); | |
168 return value; | |
169 } | |
170 private: | |
171 mutable CriticalSection cs; | |
172 bool flag; | |
tommi
2015/11/11 16:00:03
fyi - pbos is working on a change that could be he
nisse-webrtc
2015/11/12 08:39:05
I'm adding a reference to rtc::AtomicInt in the co
| |
173 }; | |
174 | |
140 // Function objects to test Thread::Invoke. | 175 // Function objects to test Thread::Invoke. |
141 struct FunctorA { | 176 struct FunctorA { |
142 int operator()() { return 42; } | 177 int operator()() { return 42; } |
143 }; | 178 }; |
144 class FunctorB { | 179 class FunctorB { |
145 public: | 180 public: |
146 explicit FunctorB(bool* flag) : flag_(flag) {} | 181 explicit FunctorB(AtomicFlag* flag) : flag_(flag) {} |
147 void operator()() { if (flag_) *flag_ = true; } | 182 void operator()() { if (flag_) *flag_ = true; } |
148 private: | 183 private: |
149 bool* flag_; | 184 AtomicFlag* flag_; |
150 }; | 185 }; |
151 struct FunctorC { | 186 struct FunctorC { |
152 int operator()() { | 187 int operator()() { |
153 Thread::Current()->ProcessMessages(50); | 188 Thread::Current()->ProcessMessages(50); |
154 return 24; | 189 return 24; |
155 } | 190 } |
156 }; | 191 }; |
157 | 192 |
158 // See: https://code.google.com/p/webrtc/issues/detail?id=2409 | 193 // See: https://code.google.com/p/webrtc/issues/detail?id=2409 |
159 TEST(ThreadTest, DISABLED_Main) { | 194 TEST(ThreadTest, DISABLED_Main) { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 delete cthread; | 294 delete cthread; |
260 current_thread->WrapCurrent(); | 295 current_thread->WrapCurrent(); |
261 } | 296 } |
262 | 297 |
263 TEST(ThreadTest, Invoke) { | 298 TEST(ThreadTest, Invoke) { |
264 // Create and start the thread. | 299 // Create and start the thread. |
265 Thread thread; | 300 Thread thread; |
266 thread.Start(); | 301 thread.Start(); |
267 // Try calling functors. | 302 // Try calling functors. |
268 EXPECT_EQ(42, thread.Invoke<int>(FunctorA())); | 303 EXPECT_EQ(42, thread.Invoke<int>(FunctorA())); |
269 bool called = false; | 304 AtomicFlag called = false; |
270 FunctorB f2(&called); | 305 FunctorB f2(&called); |
271 thread.Invoke<void>(f2); | 306 thread.Invoke<void>(f2); |
272 EXPECT_TRUE(called); | 307 EXPECT_TRUE(called); |
273 // Try calling bare functions. | 308 // Try calling bare functions. |
274 struct LocalFuncs { | 309 struct LocalFuncs { |
275 static int Func1() { return 999; } | 310 static int Func1() { return 999; } |
276 static void Func2() {} | 311 static void Func2() {} |
277 }; | 312 }; |
278 EXPECT_EQ(999, thread.Invoke<int>(&LocalFuncs::Func1)); | 313 EXPECT_EQ(999, thread.Invoke<int>(&LocalFuncs::Func1)); |
279 thread.Invoke<void>(&LocalFuncs::Func2); | 314 thread.Invoke<void>(&LocalFuncs::Func2); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
401 Event invoke_started_; | 436 Event invoke_started_; |
402 Thread* expected_thread_; | 437 Thread* expected_thread_; |
403 }; | 438 }; |
404 | 439 |
405 TEST_F(AsyncInvokeTest, FireAndForget) { | 440 TEST_F(AsyncInvokeTest, FireAndForget) { |
406 AsyncInvoker invoker; | 441 AsyncInvoker invoker; |
407 // Create and start the thread. | 442 // Create and start the thread. |
408 Thread thread; | 443 Thread thread; |
409 thread.Start(); | 444 thread.Start(); |
410 // Try calling functor. | 445 // Try calling functor. |
411 bool called = false; | 446 AtomicFlag called = false; |
412 invoker.AsyncInvoke<void>(&thread, FunctorB(&called)); | 447 invoker.AsyncInvoke<void>(&thread, FunctorB(&called)); |
413 EXPECT_TRUE_WAIT(called, kWaitTimeout); | 448 EXPECT_TRUE_WAIT(called, kWaitTimeout); |
414 } | 449 } |
415 | 450 |
416 TEST_F(AsyncInvokeTest, WithCallback) { | 451 TEST_F(AsyncInvokeTest, WithCallback) { |
417 AsyncInvoker invoker; | 452 AsyncInvoker invoker; |
418 // Create and start the thread. | 453 // Create and start the thread. |
419 Thread thread; | 454 Thread thread; |
420 thread.Start(); | 455 thread.Start(); |
421 // Try calling functor. | 456 // Try calling functor. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 // Wait for the call to begin. | 506 // Wait for the call to begin. |
472 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); | 507 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); |
473 } | 508 } |
474 // Invoker is destroyed. Function should not execute. | 509 // Invoker is destroyed. Function should not execute. |
475 Thread::Current()->ProcessMessages(kWaitTimeout); | 510 Thread::Current()->ProcessMessages(kWaitTimeout); |
476 EXPECT_EQ(0, int_value_); | 511 EXPECT_EQ(0, int_value_); |
477 } | 512 } |
478 | 513 |
479 TEST_F(AsyncInvokeTest, Flush) { | 514 TEST_F(AsyncInvokeTest, Flush) { |
480 AsyncInvoker invoker; | 515 AsyncInvoker invoker; |
481 bool flag1 = false; | 516 AtomicFlag flag1 = false; |
482 bool flag2 = false; | 517 AtomicFlag flag2 = false; |
483 // Queue two async calls to the current thread. | 518 // Queue two async calls to the current thread. |
484 invoker.AsyncInvoke<void>(Thread::Current(), | 519 invoker.AsyncInvoke<void>(Thread::Current(), |
485 FunctorB(&flag1)); | 520 FunctorB(&flag1)); |
486 invoker.AsyncInvoke<void>(Thread::Current(), | 521 invoker.AsyncInvoke<void>(Thread::Current(), |
487 FunctorB(&flag2)); | 522 FunctorB(&flag2)); |
488 // Because we haven't pumped messages, these should not have run yet. | 523 // Because we haven't pumped messages, these should not have run yet. |
489 EXPECT_FALSE(flag1); | 524 EXPECT_FALSE(flag1); |
490 EXPECT_FALSE(flag2); | 525 EXPECT_FALSE(flag2); |
491 // Force them to run now. | 526 // Force them to run now. |
492 invoker.Flush(Thread::Current()); | 527 invoker.Flush(Thread::Current()); |
493 EXPECT_TRUE(flag1); | 528 EXPECT_TRUE(flag1); |
494 EXPECT_TRUE(flag2); | 529 EXPECT_TRUE(flag2); |
495 } | 530 } |
496 | 531 |
497 TEST_F(AsyncInvokeTest, FlushWithIds) { | 532 TEST_F(AsyncInvokeTest, FlushWithIds) { |
498 AsyncInvoker invoker; | 533 AsyncInvoker invoker; |
499 bool flag1 = false; | 534 AtomicFlag flag1 = false; |
500 bool flag2 = false; | 535 AtomicFlag flag2 = false; |
501 // Queue two async calls to the current thread, one with a message id. | 536 // Queue two async calls to the current thread, one with a message id. |
502 invoker.AsyncInvoke<void>(Thread::Current(), | 537 invoker.AsyncInvoke<void>(Thread::Current(), |
503 FunctorB(&flag1), | 538 FunctorB(&flag1), |
504 5); | 539 5); |
505 invoker.AsyncInvoke<void>(Thread::Current(), | 540 invoker.AsyncInvoke<void>(Thread::Current(), |
506 FunctorB(&flag2)); | 541 FunctorB(&flag2)); |
507 // Because we haven't pumped messages, these should not have run yet. | 542 // Because we haven't pumped messages, these should not have run yet. |
508 EXPECT_FALSE(flag1); | 543 EXPECT_FALSE(flag1); |
509 EXPECT_FALSE(flag2); | 544 EXPECT_FALSE(flag2); |
510 // Execute pending calls with id == 5. | 545 // Execute pending calls with id == 5. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) { | 592 TEST_F(GuardedAsyncInvokeTest, KillThreadFireAndForget) { |
558 // Create and start the thread. | 593 // Create and start the thread. |
559 scoped_ptr<Thread> thread(new Thread()); | 594 scoped_ptr<Thread> thread(new Thread()); |
560 thread->Start(); | 595 thread->Start(); |
561 scoped_ptr<GuardedAsyncInvoker> invoker; | 596 scoped_ptr<GuardedAsyncInvoker> invoker; |
562 // Create the invoker on |thread|. | 597 // Create the invoker on |thread|. |
563 thread->Invoke<void>(CreateInvoker(&invoker)); | 598 thread->Invoke<void>(CreateInvoker(&invoker)); |
564 // Kill |thread|. | 599 // Kill |thread|. |
565 thread = nullptr; | 600 thread = nullptr; |
566 // Try calling functor. | 601 // Try calling functor. |
567 bool called = false; | 602 AtomicFlag called = false; |
568 EXPECT_FALSE(invoker->AsyncInvoke<void>(FunctorB(&called))); | 603 EXPECT_FALSE(invoker->AsyncInvoke<void>(FunctorB(&called))); |
569 // With thread gone, nothing should happen. | 604 // With thread gone, nothing should happen. |
570 WAIT(called, kWaitTimeout); | 605 WAIT(called, kWaitTimeout); |
571 EXPECT_FALSE(called); | 606 EXPECT_FALSE(called); |
572 } | 607 } |
573 | 608 |
574 // Test that we can call AsyncInvoke with callback after the thread died. | 609 // Test that we can call AsyncInvoke with callback after the thread died. |
575 TEST_F(GuardedAsyncInvokeTest, KillThreadWithCallback) { | 610 TEST_F(GuardedAsyncInvokeTest, KillThreadWithCallback) { |
576 // Create and start the thread. | 611 // Create and start the thread. |
577 scoped_ptr<Thread> thread(new Thread()); | 612 scoped_ptr<Thread> thread(new Thread()); |
(...skipping 10 matching lines...) Expand all Loading... | |
588 // With thread gone, callback should be cancelled. | 623 // With thread gone, callback should be cancelled. |
589 Thread::Current()->ProcessMessages(kWaitTimeout); | 624 Thread::Current()->ProcessMessages(kWaitTimeout); |
590 EXPECT_EQ(0, int_value_); | 625 EXPECT_EQ(0, int_value_); |
591 } | 626 } |
592 | 627 |
593 // The remaining tests check that GuardedAsyncInvoker behaves as AsyncInvoker | 628 // The remaining tests check that GuardedAsyncInvoker behaves as AsyncInvoker |
594 // when Thread is still alive. | 629 // when Thread is still alive. |
595 TEST_F(GuardedAsyncInvokeTest, FireAndForget) { | 630 TEST_F(GuardedAsyncInvokeTest, FireAndForget) { |
596 GuardedAsyncInvoker invoker; | 631 GuardedAsyncInvoker invoker; |
597 // Try calling functor. | 632 // Try calling functor. |
598 bool called = false; | 633 AtomicFlag called = false; |
599 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&called))); | 634 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&called))); |
600 EXPECT_TRUE_WAIT(called, kWaitTimeout); | 635 EXPECT_TRUE_WAIT(called, kWaitTimeout); |
601 } | 636 } |
602 | 637 |
603 TEST_F(GuardedAsyncInvokeTest, WithCallback) { | 638 TEST_F(GuardedAsyncInvokeTest, WithCallback) { |
604 GuardedAsyncInvoker invoker; | 639 GuardedAsyncInvoker invoker; |
605 // Try calling functor. | 640 // Try calling functor. |
606 SetExpectedThreadForIntCallback(Thread::Current()); | 641 SetExpectedThreadForIntCallback(Thread::Current()); |
607 EXPECT_TRUE(invoker.AsyncInvoke(FunctorA(), | 642 EXPECT_TRUE(invoker.AsyncInvoke(FunctorA(), |
608 &GuardedAsyncInvokeTest::IntCallback, | 643 &GuardedAsyncInvokeTest::IntCallback, |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
653 // Wait for the call to begin. | 688 // Wait for the call to begin. |
654 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); | 689 ASSERT_TRUE(invoke_started_.Wait(kWaitTimeout)); |
655 } | 690 } |
656 // Invoker is destroyed. Function should not execute. | 691 // Invoker is destroyed. Function should not execute. |
657 Thread::Current()->ProcessMessages(kWaitTimeout); | 692 Thread::Current()->ProcessMessages(kWaitTimeout); |
658 EXPECT_EQ(0, int_value_); | 693 EXPECT_EQ(0, int_value_); |
659 } | 694 } |
660 | 695 |
661 TEST_F(GuardedAsyncInvokeTest, Flush) { | 696 TEST_F(GuardedAsyncInvokeTest, Flush) { |
662 GuardedAsyncInvoker invoker; | 697 GuardedAsyncInvoker invoker; |
663 bool flag1 = false; | 698 AtomicFlag flag1 = false; |
664 bool flag2 = false; | 699 AtomicFlag flag2 = false; |
665 // Queue two async calls to the current thread. | 700 // Queue two async calls to the current thread. |
666 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1))); | 701 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1))); |
667 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2))); | 702 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2))); |
668 // Because we haven't pumped messages, these should not have run yet. | 703 // Because we haven't pumped messages, these should not have run yet. |
669 EXPECT_FALSE(flag1); | 704 EXPECT_FALSE(flag1); |
670 EXPECT_FALSE(flag2); | 705 EXPECT_FALSE(flag2); |
671 // Force them to run now. | 706 // Force them to run now. |
672 EXPECT_TRUE(invoker.Flush()); | 707 EXPECT_TRUE(invoker.Flush()); |
673 EXPECT_TRUE(flag1); | 708 EXPECT_TRUE(flag1); |
674 EXPECT_TRUE(flag2); | 709 EXPECT_TRUE(flag2); |
675 } | 710 } |
676 | 711 |
677 TEST_F(GuardedAsyncInvokeTest, FlushWithIds) { | 712 TEST_F(GuardedAsyncInvokeTest, FlushWithIds) { |
678 GuardedAsyncInvoker invoker; | 713 GuardedAsyncInvoker invoker; |
679 bool flag1 = false; | 714 AtomicFlag flag1 = false; |
680 bool flag2 = false; | 715 AtomicFlag flag2 = false; |
681 // Queue two async calls to the current thread, one with a message id. | 716 // Queue two async calls to the current thread, one with a message id. |
682 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1), 5)); | 717 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag1), 5)); |
683 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2))); | 718 EXPECT_TRUE(invoker.AsyncInvoke<void>(FunctorB(&flag2))); |
684 // Because we haven't pumped messages, these should not have run yet. | 719 // Because we haven't pumped messages, these should not have run yet. |
685 EXPECT_FALSE(flag1); | 720 EXPECT_FALSE(flag1); |
686 EXPECT_FALSE(flag2); | 721 EXPECT_FALSE(flag2); |
687 // Execute pending calls with id == 5. | 722 // Execute pending calls with id == 5. |
688 EXPECT_TRUE(invoker.Flush(5)); | 723 EXPECT_TRUE(invoker.Flush(5)); |
689 EXPECT_TRUE(flag1); | 724 EXPECT_TRUE(flag1); |
690 EXPECT_FALSE(flag2); | 725 EXPECT_FALSE(flag2); |
(...skipping 22 matching lines...) Expand all Loading... | |
713 }; | 748 }; |
714 | 749 |
715 TEST_F(ComThreadTest, ComInited) { | 750 TEST_F(ComThreadTest, ComInited) { |
716 Thread* thread = new ComThread(); | 751 Thread* thread = new ComThread(); |
717 EXPECT_TRUE(thread->Start()); | 752 EXPECT_TRUE(thread->Start()); |
718 thread->Post(this, 0); | 753 thread->Post(this, 0); |
719 EXPECT_TRUE_WAIT(done_, 1000); | 754 EXPECT_TRUE_WAIT(done_, 1000); |
720 delete thread; | 755 delete thread; |
721 } | 756 } |
722 #endif | 757 #endif |
OLD | NEW |