| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/weak_ptr.h" | 5 #include "base/memory/weak_ptr.h" |
| 6 | 6 |
| 7 #include <memory> |
| 7 #include <string> | 8 #include <string> |
| 8 | 9 |
| 9 #include "base/bind.h" | 10 #include "base/bind.h" |
| 10 #include "base/debug/leak_annotations.h" | 11 #include "base/debug/leak_annotations.h" |
| 11 #include "base/location.h" | 12 #include "base/location.h" |
| 12 #include "base/memory/scoped_ptr.h" | |
| 13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 14 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
| 15 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 17 |
| 18 namespace base { | 18 namespace base { |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 template <class T> | 21 template <class T> |
| 22 class OffThreadObjectCreator { | 22 class OffThreadObjectCreator { |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 WeakPtr<int> ptr = factory.GetWeakPtr(); | 320 WeakPtr<int> ptr = factory.GetWeakPtr(); |
| 321 EXPECT_TRUE(factory.HasWeakPtrs()); | 321 EXPECT_TRUE(factory.HasWeakPtrs()); |
| 322 } | 322 } |
| 323 EXPECT_FALSE(factory.HasWeakPtrs()); | 323 EXPECT_FALSE(factory.HasWeakPtrs()); |
| 324 } | 324 } |
| 325 | 325 |
| 326 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) { | 326 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) { |
| 327 // Test that it is OK to create an object that supports WeakPtr on one thread, | 327 // Test that it is OK to create an object that supports WeakPtr on one thread, |
| 328 // but use it on another. This tests that we do not trip runtime checks that | 328 // but use it on another. This tests that we do not trip runtime checks that |
| 329 // ensure that a WeakPtr is not used by multiple threads. | 329 // ensure that a WeakPtr is not used by multiple threads. |
| 330 scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject()); | 330 std::unique_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject()); |
| 331 WeakPtr<Target> weak_ptr = target->AsWeakPtr(); | 331 WeakPtr<Target> weak_ptr = target->AsWeakPtr(); |
| 332 EXPECT_EQ(target.get(), weak_ptr.get()); | 332 EXPECT_EQ(target.get(), weak_ptr.get()); |
| 333 } | 333 } |
| 334 | 334 |
| 335 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) { | 335 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) { |
| 336 // Test that it is OK to create an object that has a WeakPtr member on one | 336 // Test that it is OK to create an object that has a WeakPtr member on one |
| 337 // thread, but use it on another. This tests that we do not trip runtime | 337 // thread, but use it on another. This tests that we do not trip runtime |
| 338 // checks that ensure that a WeakPtr is not used by multiple threads. | 338 // checks that ensure that a WeakPtr is not used by multiple threads. |
| 339 scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject()); | 339 std::unique_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject()); |
| 340 Target target; | 340 Target target; |
| 341 arrow->target = target.AsWeakPtr(); | 341 arrow->target = target.AsWeakPtr(); |
| 342 EXPECT_EQ(&target, arrow->target.get()); | 342 EXPECT_EQ(&target, arrow->target.get()); |
| 343 } | 343 } |
| 344 | 344 |
| 345 TEST(WeakPtrTest, MoveOwnershipImplicitly) { | 345 TEST(WeakPtrTest, MoveOwnershipImplicitly) { |
| 346 // Move object ownership to another thread by releasing all weak pointers | 346 // Move object ownership to another thread by releasing all weak pointers |
| 347 // on the original thread first, and then establish WeakPtr on a different | 347 // on the original thread first, and then establish WeakPtr on a different |
| 348 // thread. | 348 // thread. |
| 349 BackgroundThread background; | 349 BackgroundThread background; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 } | 402 } |
| 403 | 403 |
| 404 delete arrow; | 404 delete arrow; |
| 405 } | 405 } |
| 406 | 406 |
| 407 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) { | 407 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) { |
| 408 BackgroundThread background; | 408 BackgroundThread background; |
| 409 background.Start(); | 409 background.Start(); |
| 410 | 410 |
| 411 Arrow arrow; | 411 Arrow arrow; |
| 412 scoped_ptr<TargetWithFactory> target(new TargetWithFactory); | 412 std::unique_ptr<TargetWithFactory> target(new TargetWithFactory); |
| 413 | 413 |
| 414 // Bind to main thread. | 414 // Bind to main thread. |
| 415 arrow.target = target->factory.GetWeakPtr(); | 415 arrow.target = target->factory.GetWeakPtr(); |
| 416 EXPECT_EQ(target.get(), arrow.target.get()); | 416 EXPECT_EQ(target.get(), arrow.target.get()); |
| 417 | 417 |
| 418 target->factory.InvalidateWeakPtrs(); | 418 target->factory.InvalidateWeakPtrs(); |
| 419 EXPECT_EQ(NULL, arrow.target.get()); | 419 EXPECT_EQ(NULL, arrow.target.get()); |
| 420 | 420 |
| 421 arrow.target = target->factory.GetWeakPtr(); | 421 arrow.target = target->factory.GetWeakPtr(); |
| 422 // Re-bind to background thread. | 422 // Re-bind to background thread. |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 BackgroundThread background; | 572 BackgroundThread background; |
| 573 background.Start(); | 573 background.Start(); |
| 574 ASSERT_DEATH(background.DeRef(&arrow), ""); | 574 ASSERT_DEATH(background.DeRef(&arrow), ""); |
| 575 } | 575 } |
| 576 | 576 |
| 577 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) { | 577 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) { |
| 578 // The default style "fast" does not support multi-threaded tests | 578 // The default style "fast" does not support multi-threaded tests |
| 579 // (introduces deadlock on Linux). | 579 // (introduces deadlock on Linux). |
| 580 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 580 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 581 | 581 |
| 582 scoped_ptr<Target> target(new Target()); | 582 std::unique_ptr<Target> target(new Target()); |
| 583 | 583 |
| 584 // Main thread creates an arrow referencing the Target. | 584 // Main thread creates an arrow referencing the Target. |
| 585 Arrow arrow; | 585 Arrow arrow; |
| 586 arrow.target = target->AsWeakPtr(); | 586 arrow.target = target->AsWeakPtr(); |
| 587 | 587 |
| 588 // Background thread tries to deref target, binding it to the thread. | 588 // Background thread tries to deref target, binding it to the thread. |
| 589 BackgroundThread background; | 589 BackgroundThread background; |
| 590 background.Start(); | 590 background.Start(); |
| 591 background.DeRef(&arrow); | 591 background.DeRef(&arrow); |
| 592 | 592 |
| 593 // Main thread deletes Target, violating thread binding. | 593 // Main thread deletes Target, violating thread binding. |
| 594 ASSERT_DEATH(target.reset(), ""); | 594 ASSERT_DEATH(target.reset(), ""); |
| 595 | 595 |
| 596 // |target.reset()| died so |target| still holds the object, so we | 596 // |target.reset()| died so |target| still holds the object, so we |
| 597 // must pass it to the background thread to teardown. | 597 // must pass it to the background thread to teardown. |
| 598 background.DeleteTarget(target.release()); | 598 background.DeleteTarget(target.release()); |
| 599 } | 599 } |
| 600 | 600 |
| 601 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) { | 601 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) { |
| 602 // The default style "fast" does not support multi-threaded tests | 602 // The default style "fast" does not support multi-threaded tests |
| 603 // (introduces deadlock on Linux). | 603 // (introduces deadlock on Linux). |
| 604 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 604 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 605 | 605 |
| 606 scoped_ptr<Target> target(new Target()); | 606 std::unique_ptr<Target> target(new Target()); |
| 607 | 607 |
| 608 // Main thread creates an arrow referencing the Target, and references it, so | 608 // Main thread creates an arrow referencing the Target, and references it, so |
| 609 // that it becomes bound to the thread. | 609 // that it becomes bound to the thread. |
| 610 Arrow arrow; | 610 Arrow arrow; |
| 611 arrow.target = target->AsWeakPtr(); | 611 arrow.target = target->AsWeakPtr(); |
| 612 arrow.target.get(); | 612 arrow.target.get(); |
| 613 | 613 |
| 614 // Background thread tries to delete target, volating thread binding. | 614 // Background thread tries to delete target, volating thread binding. |
| 615 BackgroundThread background; | 615 BackgroundThread background; |
| 616 background.Start(); | 616 background.Start(); |
| 617 ASSERT_DEATH(background.DeleteTarget(target.release()), ""); | 617 ASSERT_DEATH(background.DeleteTarget(target.release()), ""); |
| 618 } | 618 } |
| 619 | 619 |
| 620 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) { | 620 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) { |
| 621 // The default style "fast" does not support multi-threaded tests | 621 // The default style "fast" does not support multi-threaded tests |
| 622 // (introduces deadlock on Linux). | 622 // (introduces deadlock on Linux). |
| 623 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; | 623 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 624 | 624 |
| 625 scoped_ptr<Target> target(new Target()); | 625 std::unique_ptr<Target> target(new Target()); |
| 626 | 626 |
| 627 // Main thread creates an arrow referencing the Target. | 627 // Main thread creates an arrow referencing the Target. |
| 628 Arrow arrow; | 628 Arrow arrow; |
| 629 arrow.target = target->AsWeakPtr(); | 629 arrow.target = target->AsWeakPtr(); |
| 630 | 630 |
| 631 // Background thread tries to delete target, binding the object to the thread. | 631 // Background thread tries to delete target, binding the object to the thread. |
| 632 BackgroundThread background; | 632 BackgroundThread background; |
| 633 background.Start(); | 633 background.Start(); |
| 634 background.DeleteTarget(target.release()); | 634 background.DeleteTarget(target.release()); |
| 635 | 635 |
| 636 // Main thread attempts to dereference the target, violating thread binding. | 636 // Main thread attempts to dereference the target, violating thread binding. |
| 637 ASSERT_DEATH(arrow.target.get(), ""); | 637 ASSERT_DEATH(arrow.target.get(), ""); |
| 638 } | 638 } |
| 639 | 639 |
| 640 #endif | 640 #endif |
| 641 | 641 |
| 642 } // namespace base | 642 } // namespace base |
| OLD | NEW |