| 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 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 // executing, and then to wait for it to finish, ensuring the "EXPECT_FALSE" | 451 // executing, and then to wait for it to finish, ensuring the "EXPECT_FALSE" |
| 452 // is run. | 452 // is run. |
| 453 Event functor_started(false, false); | 453 Event functor_started(false, false); |
| 454 Event functor_continue(false, false); | 454 Event functor_continue(false, false); |
| 455 Event functor_finished(false, false); | 455 Event functor_finished(false, false); |
| 456 | 456 |
| 457 auto thread = Thread::CreateWithSocketServer(); | 457 auto thread = Thread::CreateWithSocketServer(); |
| 458 thread->Start(); | 458 thread->Start(); |
| 459 volatile bool invoker_destroyed = false; | 459 volatile bool invoker_destroyed = false; |
| 460 { | 460 { |
| 461 auto functor = [&functor_started, &functor_continue, &functor_finished, |
| 462 &invoker_destroyed] { |
| 463 functor_started.Set(); |
| 464 functor_continue.Wait(Event::kForever); |
| 465 rtc::Thread::Current()->SleepMs(kWaitTimeout); |
| 466 EXPECT_FALSE(invoker_destroyed); |
| 467 functor_finished.Set(); |
| 468 }; |
| 461 AsyncInvoker invoker; | 469 AsyncInvoker invoker; |
| 462 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), | 470 invoker.AsyncInvoke<void>(RTC_FROM_HERE, thread.get(), functor); |
| 463 [&functor_started, &functor_continue, | |
| 464 &functor_finished, &invoker_destroyed] { | |
| 465 functor_started.Set(); | |
| 466 functor_continue.Wait(Event::kForever); | |
| 467 rtc::Thread::Current()->SleepMs(kWaitTimeout); | |
| 468 EXPECT_FALSE(invoker_destroyed); | |
| 469 functor_finished.Set(); | |
| 470 }); | |
| 471 functor_started.Wait(Event::kForever); | 471 functor_started.Wait(Event::kForever); |
| 472 | 472 |
| 473 // Allow the functor to continue and immediately destroy the invoker. | 473 // Destroy the invoker while the functor is still executing (doing |
| 474 // SleepMs). |
| 474 functor_continue.Set(); | 475 functor_continue.Set(); |
| 475 } | 476 } |
| 476 | 477 |
| 477 // If the destructor DIDN'T wait for the functor to finish executing, it will | 478 // If the destructor DIDN'T wait for the functor to finish executing, it will |
| 478 // hit the EXPECT_FALSE(invoker_destroyed) after it finishes sleeping for a | 479 // hit the EXPECT_FALSE(invoker_destroyed) after it finishes sleeping for a |
| 479 // second. | 480 // second. |
| 480 invoker_destroyed = true; | 481 invoker_destroyed = true; |
| 481 functor_finished.Wait(Event::kForever); | 482 functor_finished.Wait(Event::kForever); |
| 482 } | 483 } |
| 483 | 484 |
| 485 // Variant of the above test where the async-invoked task calls AsyncInvoke |
| 486 // *again*, for the thread on which the AsyncInvoker is currently being |
| 487 // destroyed. This shouldn't deadlock or crash; this second invocation should |
| 488 // just be ignored. |
| 489 TEST_F(AsyncInvokeTest, KillInvokerDuringExecuteWithReentrantInvoke) { |
| 490 Event functor_started(false, false); |
| 491 // Flag used to verify that the recursively invoked task never actually runs. |
| 492 bool reentrant_functor_run = false; |
| 493 |
| 494 Thread* main = Thread::Current(); |
| 495 Thread thread; |
| 496 thread.Start(); |
| 497 { |
| 498 AsyncInvoker invoker; |
| 499 auto reentrant_functor = [&reentrant_functor_run] { |
| 500 reentrant_functor_run = true; |
| 501 }; |
| 502 auto functor = [&functor_started, &invoker, main, reentrant_functor] { |
| 503 functor_started.Set(); |
| 504 Thread::Current()->SleepMs(kWaitTimeout); |
| 505 invoker.AsyncInvoke<void>(RTC_FROM_HERE, main, reentrant_functor); |
| 506 }; |
| 507 // This queues a task on |thread| to sleep for |kWaitTimeout| then queue a |
| 508 // task on |main|. But this second queued task should never run, since the |
| 509 // destructor will be entered before it's even invoked. |
| 510 invoker.AsyncInvoke<void>(RTC_FROM_HERE, &thread, functor); |
| 511 functor_started.Wait(Event::kForever); |
| 512 } |
| 513 EXPECT_FALSE(reentrant_functor_run); |
| 514 } |
| 515 |
| 484 TEST_F(AsyncInvokeTest, Flush) { | 516 TEST_F(AsyncInvokeTest, Flush) { |
| 485 AsyncInvoker invoker; | 517 AsyncInvoker invoker; |
| 486 AtomicBool flag1; | 518 AtomicBool flag1; |
| 487 AtomicBool flag2; | 519 AtomicBool flag2; |
| 488 // Queue two async calls to the current thread. | 520 // Queue two async calls to the current thread. |
| 489 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1)); | 521 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag1)); |
| 490 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2)); | 522 invoker.AsyncInvoke<void>(RTC_FROM_HERE, Thread::Current(), FunctorB(&flag2)); |
| 491 // 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. |
| 492 EXPECT_FALSE(flag1.get()); | 524 EXPECT_FALSE(flag1.get()); |
| 493 EXPECT_FALSE(flag2.get()); | 525 EXPECT_FALSE(flag2.get()); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 // Execute pending calls with id == 5. | 636 // Execute pending calls with id == 5. |
| 605 EXPECT_TRUE(invoker.Flush(5)); | 637 EXPECT_TRUE(invoker.Flush(5)); |
| 606 EXPECT_TRUE(flag1.get()); | 638 EXPECT_TRUE(flag1.get()); |
| 607 EXPECT_FALSE(flag2.get()); | 639 EXPECT_FALSE(flag2.get()); |
| 608 flag1 = false; | 640 flag1 = false; |
| 609 // Execute all pending calls. The id == 5 call should not execute again. | 641 // Execute all pending calls. The id == 5 call should not execute again. |
| 610 EXPECT_TRUE(invoker.Flush()); | 642 EXPECT_TRUE(invoker.Flush()); |
| 611 EXPECT_FALSE(flag1.get()); | 643 EXPECT_FALSE(flag1.get()); |
| 612 EXPECT_TRUE(flag2.get()); | 644 EXPECT_TRUE(flag2.get()); |
| 613 } | 645 } |
| OLD | NEW |