Home | History | Annotate | Download | only in memory
      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
      3 // found in the LICENSE file.
      4 
      5 #include "base/memory/weak_ptr.h"
      6 
      7 #include <string>
      8 
      9 #include "base/bind.h"
     10 #include "base/debug/leak_annotations.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "base/synchronization/waitable_event.h"
     14 #include "base/threading/thread.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace base {
     18 namespace {
     19 
     20 template <class T>
     21 class OffThreadObjectCreator {
     22  public:
     23   static T* NewObject() {
     24     T* result;
     25     {
     26       Thread creator_thread("creator_thread");
     27       creator_thread.Start();
     28       creator_thread.message_loop()->PostTask(
     29           FROM_HERE,
     30           base::Bind(OffThreadObjectCreator::CreateObject, &result));
     31     }
     32     DCHECK(result);  // We synchronized on thread destruction above.
     33     return result;
     34   }
     35  private:
     36   static void CreateObject(T** result) {
     37     *result = new T;
     38   }
     39 };
     40 
     41 struct Base {
     42   std::string member;
     43 };
     44 struct Derived : public Base {};
     45 
     46 struct TargetBase {};
     47 struct Target : public TargetBase, public SupportsWeakPtr<Target> {
     48   virtual ~Target() {}
     49 };
     50 struct DerivedTarget : public Target {};
     51 struct Arrow {
     52   WeakPtr<Target> target;
     53 };
     54 struct TargetWithFactory : public Target {
     55   TargetWithFactory() : factory(this) {}
     56   WeakPtrFactory<Target> factory;
     57 };
     58 
     59 // Helper class to create and destroy weak pointer copies
     60 // and delete objects on a background thread.
     61 class BackgroundThread : public Thread {
     62  public:
     63   BackgroundThread() : Thread("owner_thread") {}
     64 
     65   virtual ~BackgroundThread() {
     66     Stop();
     67   }
     68 
     69   void CreateArrowFromTarget(Arrow** arrow, Target* target) {
     70     WaitableEvent completion(true, false);
     71     message_loop()->PostTask(
     72         FROM_HERE,
     73         base::Bind(&BackgroundThread::DoCreateArrowFromTarget,
     74                    arrow, target, &completion));
     75     completion.Wait();
     76   }
     77 
     78   void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
     79     WaitableEvent completion(true, false);
     80     message_loop()->PostTask(
     81         FROM_HERE,
     82         base::Bind(&BackgroundThread::DoCreateArrowFromArrow,
     83                    arrow, other, &completion));
     84     completion.Wait();
     85   }
     86 
     87   void DeleteTarget(Target* object) {
     88     WaitableEvent completion(true, false);
     89     message_loop()->PostTask(
     90         FROM_HERE,
     91         base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion));
     92     completion.Wait();
     93   }
     94 
     95   void CopyAndAssignArrow(Arrow* object) {
     96     WaitableEvent completion(true, false);
     97     message_loop()->PostTask(
     98         FROM_HERE,
     99         base::Bind(&BackgroundThread::DoCopyAndAssignArrow,
    100                    object, &completion));
    101     completion.Wait();
    102   }
    103 
    104   void CopyAndAssignArrowBase(Arrow* object) {
    105     WaitableEvent completion(true, false);
    106     message_loop()->PostTask(
    107         FROM_HERE,
    108         base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase,
    109                    object, &completion));
    110     completion.Wait();
    111   }
    112 
    113   void DeleteArrow(Arrow* object) {
    114     WaitableEvent completion(true, false);
    115     message_loop()->PostTask(
    116         FROM_HERE,
    117         base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion));
    118     completion.Wait();
    119   }
    120 
    121   Target* DeRef(const Arrow* arrow) {
    122     WaitableEvent completion(true, false);
    123     Target* result = NULL;
    124     message_loop()->PostTask(
    125         FROM_HERE,
    126         base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion));
    127     completion.Wait();
    128     return result;
    129   }
    130 
    131  protected:
    132   static void DoCreateArrowFromArrow(Arrow** arrow,
    133                                      const Arrow* other,
    134                                      WaitableEvent* completion) {
    135     *arrow = new Arrow;
    136     **arrow = *other;
    137     completion->Signal();
    138   }
    139 
    140   static void DoCreateArrowFromTarget(Arrow** arrow,
    141                                       Target* target,
    142                                       WaitableEvent* completion) {
    143     *arrow = new Arrow;
    144     (*arrow)->target = target->AsWeakPtr();
    145     completion->Signal();
    146   }
    147 
    148   static void DoDeRef(const Arrow* arrow,
    149                       Target** result,
    150                       WaitableEvent* completion) {
    151     *result = arrow->target.get();
    152     completion->Signal();
    153   }
    154 
    155   static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
    156     delete object;
    157     completion->Signal();
    158   }
    159 
    160   static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
    161     // Copy constructor.
    162     Arrow a = *object;
    163     // Assignment operator.
    164     *object = a;
    165     completion->Signal();
    166   }
    167 
    168   static void DoCopyAndAssignArrowBase(
    169       Arrow* object,
    170       WaitableEvent* completion) {
    171     // Copy constructor.
    172     WeakPtr<TargetBase> b = object->target;
    173     // Assignment operator.
    174     WeakPtr<TargetBase> c;
    175     c = object->target;
    176     completion->Signal();
    177   }
    178 
    179   static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
    180     delete object;
    181     completion->Signal();
    182   }
    183 };
    184 
    185 }  // namespace
    186 
    187 TEST(WeakPtrFactoryTest, Basic) {
    188   int data;
    189   WeakPtrFactory<int> factory(&data);
    190   WeakPtr<int> ptr = factory.GetWeakPtr();
    191   EXPECT_EQ(&data, ptr.get());
    192 }
    193 
    194 TEST(WeakPtrFactoryTest, Comparison) {
    195   int data;
    196   WeakPtrFactory<int> factory(&data);
    197   WeakPtr<int> ptr = factory.GetWeakPtr();
    198   WeakPtr<int> ptr2 = ptr;
    199   EXPECT_EQ(ptr.get(), ptr2.get());
    200 }
    201 
    202 TEST(WeakPtrFactoryTest, OutOfScope) {
    203   WeakPtr<int> ptr;
    204   EXPECT_EQ(NULL, ptr.get());
    205   {
    206     int data;
    207     WeakPtrFactory<int> factory(&data);
    208     ptr = factory.GetWeakPtr();
    209   }
    210   EXPECT_EQ(NULL, ptr.get());
    211 }
    212 
    213 TEST(WeakPtrFactoryTest, Multiple) {
    214   WeakPtr<int> a, b;
    215   {
    216     int data;
    217     WeakPtrFactory<int> factory(&data);
    218     a = factory.GetWeakPtr();
    219     b = factory.GetWeakPtr();
    220     EXPECT_EQ(&data, a.get());
    221     EXPECT_EQ(&data, b.get());
    222   }
    223   EXPECT_EQ(NULL, a.get());
    224   EXPECT_EQ(NULL, b.get());
    225 }
    226 
    227 TEST(WeakPtrFactoryTest, MultipleStaged) {
    228   WeakPtr<int> a;
    229   {
    230     int data;
    231     WeakPtrFactory<int> factory(&data);
    232     a = factory.GetWeakPtr();
    233     {
    234       WeakPtr<int> b = factory.GetWeakPtr();
    235     }
    236     EXPECT_TRUE(NULL != a.get());
    237   }
    238   EXPECT_EQ(NULL, a.get());
    239 }
    240 
    241 TEST(WeakPtrFactoryTest, Dereference) {
    242   Base data;
    243   data.member = "123456";
    244   WeakPtrFactory<Base> factory(&data);
    245   WeakPtr<Base> ptr = factory.GetWeakPtr();
    246   EXPECT_EQ(&data, ptr.get());
    247   EXPECT_EQ(data.member, (*ptr).member);
    248   EXPECT_EQ(data.member, ptr->member);
    249 }
    250 
    251 TEST(WeakPtrFactoryTest, UpCast) {
    252   Derived data;
    253   WeakPtrFactory<Derived> factory(&data);
    254   WeakPtr<Base> ptr = factory.GetWeakPtr();
    255   ptr = factory.GetWeakPtr();
    256   EXPECT_EQ(ptr.get(), &data);
    257 }
    258 
    259 TEST(WeakPtrTest, SupportsWeakPtr) {
    260   Target target;
    261   WeakPtr<Target> ptr = target.AsWeakPtr();
    262   EXPECT_EQ(&target, ptr.get());
    263 }
    264 
    265 TEST(WeakPtrTest, DerivedTarget) {
    266   DerivedTarget target;
    267   WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target);
    268   EXPECT_EQ(&target, ptr.get());
    269 }
    270 
    271 TEST(WeakPtrTest, InvalidateWeakPtrs) {
    272   int data;
    273   WeakPtrFactory<int> factory(&data);
    274   WeakPtr<int> ptr = factory.GetWeakPtr();
    275   EXPECT_EQ(&data, ptr.get());
    276   EXPECT_TRUE(factory.HasWeakPtrs());
    277   factory.InvalidateWeakPtrs();
    278   EXPECT_EQ(NULL, ptr.get());
    279   EXPECT_FALSE(factory.HasWeakPtrs());
    280 }
    281 
    282 TEST(WeakPtrTest, HasWeakPtrs) {
    283   int data;
    284   WeakPtrFactory<int> factory(&data);
    285   {
    286     WeakPtr<int> ptr = factory.GetWeakPtr();
    287     EXPECT_TRUE(factory.HasWeakPtrs());
    288   }
    289   EXPECT_FALSE(factory.HasWeakPtrs());
    290 }
    291 
    292 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
    293   // Test that it is OK to create an object that supports WeakPtr on one thread,
    294   // but use it on another.  This tests that we do not trip runtime checks that
    295   // ensure that a WeakPtr is not used by multiple threads.
    296   scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
    297   WeakPtr<Target> weak_ptr = target->AsWeakPtr();
    298   EXPECT_EQ(target.get(), weak_ptr.get());
    299 }
    300 
    301 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
    302   // Test that it is OK to create an object that has a WeakPtr member on one
    303   // thread, but use it on another.  This tests that we do not trip runtime
    304   // checks that ensure that a WeakPtr is not used by multiple threads.
    305   scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
    306   Target target;
    307   arrow->target = target.AsWeakPtr();
    308   EXPECT_EQ(&target, arrow->target.get());
    309 }
    310 
    311 TEST(WeakPtrTest, MoveOwnershipImplicitly) {
    312   // Move object ownership to another thread by releasing all weak pointers
    313   // on the original thread first, and then establish WeakPtr on a different
    314   // thread.
    315   BackgroundThread background;
    316   background.Start();
    317 
    318   Target* target = new Target();
    319   {
    320     WeakPtr<Target> weak_ptr = target->AsWeakPtr();
    321     // Main thread deletes the WeakPtr, then the thread ownership of the
    322     // object can be implicitly moved.
    323   }
    324   Arrow* arrow;
    325 
    326   // Background thread creates WeakPtr(and implicitly owns the object).
    327   background.CreateArrowFromTarget(&arrow, target);
    328   EXPECT_EQ(background.DeRef(arrow), target);
    329 
    330   {
    331     // Main thread creates another WeakPtr, but this does not trigger implicitly
    332     // thread ownership move.
    333     Arrow arrow;
    334     arrow.target = target->AsWeakPtr();
    335 
    336     // The new WeakPtr is owned by background thread.
    337     EXPECT_EQ(target, background.DeRef(&arrow));
    338   }
    339 
    340   // Target can only be deleted on background thread.
    341   background.DeleteTarget(target);
    342   background.DeleteArrow(arrow);
    343 }
    344 
    345 TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
    346   BackgroundThread background;
    347   background.Start();
    348 
    349   Arrow* arrow;
    350   {
    351     Target target;
    352     // Background thread creates WeakPtr.
    353     background.CreateArrowFromTarget(&arrow, &target);
    354 
    355     // Bind to background thread.
    356     EXPECT_EQ(&target, background.DeRef(arrow));
    357 
    358     // Release the only WeakPtr.
    359     arrow->target.reset();
    360 
    361     // Now we should be able to create a new reference from this thread.
    362     arrow->target = target.AsWeakPtr();
    363 
    364     // Re-bind to main thread.
    365     EXPECT_EQ(&target, arrow->target.get());
    366 
    367     // And the main thread can now delete the target.
    368   }
    369 
    370   delete arrow;
    371 }
    372 
    373 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
    374   BackgroundThread background;
    375   background.Start();
    376 
    377   Arrow arrow;
    378   scoped_ptr<TargetWithFactory> target(new TargetWithFactory);
    379 
    380   // Bind to main thread.
    381   arrow.target = target->factory.GetWeakPtr();
    382   EXPECT_EQ(target.get(), arrow.target.get());
    383 
    384   target->factory.InvalidateWeakPtrs();
    385   EXPECT_EQ(NULL, arrow.target.get());
    386 
    387   arrow.target = target->factory.GetWeakPtr();
    388   // Re-bind to background thread.
    389   EXPECT_EQ(target.get(), background.DeRef(&arrow));
    390 
    391   // And the background thread can now delete the target.
    392   background.DeleteTarget(target.release());
    393 }
    394 
    395 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
    396   // Originating thread has a WeakPtr that outlives others.
    397   // - Main thread creates a WeakPtr
    398   // - Background thread creates a WeakPtr copy from the one in main thread
    399   // - Destruct the WeakPtr on background thread
    400   // - Destruct the WeakPtr on main thread
    401   BackgroundThread background;
    402   background.Start();
    403 
    404   Target target;
    405   Arrow arrow;
    406   arrow.target = target.AsWeakPtr();
    407 
    408   Arrow* arrow_copy;
    409   background.CreateArrowFromArrow(&arrow_copy, &arrow);
    410   EXPECT_EQ(arrow_copy->target.get(), &target);
    411   background.DeleteArrow(arrow_copy);
    412 }
    413 
    414 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
    415   // Originating thread drops all references before another thread.
    416   // - Main thread creates a WeakPtr and passes copy to background thread
    417   // - Destruct the pointer on main thread
    418   // - Destruct the pointer on background thread
    419   BackgroundThread background;
    420   background.Start();
    421 
    422   Target target;
    423   Arrow* arrow_copy;
    424   {
    425     Arrow arrow;
    426     arrow.target = target.AsWeakPtr();
    427     background.CreateArrowFromArrow(&arrow_copy, &arrow);
    428   }
    429   EXPECT_EQ(arrow_copy->target.get(), &target);
    430   background.DeleteArrow(arrow_copy);
    431 }
    432 
    433 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
    434   // Originating thread invalidates WeakPtrs while its held by other thread.
    435   // - Main thread creates WeakPtr and passes Copy to background thread
    436   // - Object gets destroyed on main thread
    437   //   (invalidates WeakPtr on background thread)
    438   // - WeakPtr gets destroyed on Thread B
    439   BackgroundThread background;
    440   background.Start();
    441   Arrow* arrow_copy;
    442   {
    443     Target target;
    444     Arrow arrow;
    445     arrow.target = target.AsWeakPtr();
    446     background.CreateArrowFromArrow(&arrow_copy, &arrow);
    447   }
    448   EXPECT_EQ(NULL, arrow_copy->target.get());
    449   background.DeleteArrow(arrow_copy);
    450 }
    451 
    452 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
    453   // Main thread creates a Target object.
    454   Target target;
    455   // Main thread creates an arrow referencing the Target.
    456   Arrow *arrow = new Arrow();
    457   arrow->target = target.AsWeakPtr();
    458 
    459   // Background can copy and assign arrow (as well as the WeakPtr inside).
    460   BackgroundThread background;
    461   background.Start();
    462   background.CopyAndAssignArrow(arrow);
    463   background.DeleteArrow(arrow);
    464 }
    465 
    466 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
    467   // Main thread creates a Target object.
    468   Target target;
    469   // Main thread creates an arrow referencing the Target.
    470   Arrow *arrow = new Arrow();
    471   arrow->target = target.AsWeakPtr();
    472 
    473   // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
    474   BackgroundThread background;
    475   background.Start();
    476   background.CopyAndAssignArrowBase(arrow);
    477   background.DeleteArrow(arrow);
    478 }
    479 
    480 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
    481   // Main thread creates a Target object.
    482   Target target;
    483   // Main thread creates an arrow referencing the Target.
    484   Arrow* arrow = new Arrow();
    485   arrow->target = target.AsWeakPtr();
    486 
    487   // Background can delete arrow (as well as the WeakPtr inside).
    488   BackgroundThread background;
    489   background.Start();
    490   background.DeleteArrow(arrow);
    491 }
    492 
    493 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
    494 
    495 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
    496   // The default style "fast" does not support multi-threaded tests
    497   // (introduces deadlock on Linux).
    498   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    499 
    500   BackgroundThread background;
    501   background.Start();
    502 
    503   // Main thread creates a Target object.
    504   Target target;
    505   // Main thread creates an arrow referencing the Target.
    506   Arrow arrow;
    507   arrow.target = target.AsWeakPtr();
    508 
    509   // Background copies the WeakPtr.
    510   Arrow* arrow_copy;
    511   background.CreateArrowFromArrow(&arrow_copy, &arrow);
    512 
    513   // The copy is still bound to main thread so I can deref.
    514   EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
    515 
    516   // Although background thread created the copy, it can not deref the copied
    517   // WeakPtr.
    518   ASSERT_DEATH(background.DeRef(arrow_copy), "");
    519 
    520   background.DeleteArrow(arrow_copy);
    521 }
    522 
    523 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
    524   // The default style "fast" does not support multi-threaded tests
    525   // (introduces deadlock on Linux).
    526   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    527 
    528   // Main thread creates a Target object.
    529   Target target;
    530 
    531   // Main thread creates an arrow referencing the Target (so target's
    532   // thread ownership can not be implicitly moved).
    533   Arrow arrow;
    534   arrow.target = target.AsWeakPtr();
    535   arrow.target.get();
    536 
    537   // Background thread tries to deref target, which violates thread ownership.
    538   BackgroundThread background;
    539   background.Start();
    540   ASSERT_DEATH(background.DeRef(&arrow), "");
    541 }
    542 
    543 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
    544   // The default style "fast" does not support multi-threaded tests
    545   // (introduces deadlock on Linux).
    546   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    547 
    548   scoped_ptr<Target> target(new Target());
    549 
    550   // Main thread creates an arrow referencing the Target.
    551   Arrow arrow;
    552   arrow.target = target->AsWeakPtr();
    553 
    554   // Background thread tries to deref target, binding it to the thread.
    555   BackgroundThread background;
    556   background.Start();
    557   background.DeRef(&arrow);
    558 
    559   // Main thread deletes Target, violating thread binding.
    560   ASSERT_DEATH(target.reset(), "");
    561 
    562   // |target.reset()| died so |target| still holds the object, so we
    563   // must pass it to the background thread to teardown.
    564   background.DeleteTarget(target.release());
    565 }
    566 
    567 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
    568   // The default style "fast" does not support multi-threaded tests
    569   // (introduces deadlock on Linux).
    570   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    571 
    572   scoped_ptr<Target> target(new Target());
    573 
    574   // Main thread creates an arrow referencing the Target, and references it, so
    575   // that it becomes bound to the thread.
    576   Arrow arrow;
    577   arrow.target = target->AsWeakPtr();
    578   arrow.target.get();
    579 
    580   // Background thread tries to delete target, volating thread binding.
    581   BackgroundThread background;
    582   background.Start();
    583   ASSERT_DEATH(background.DeleteTarget(target.release()), "");
    584 }
    585 
    586 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
    587   // The default style "fast" does not support multi-threaded tests
    588   // (introduces deadlock on Linux).
    589   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    590 
    591   scoped_ptr<Target> target(new Target());
    592 
    593   // Main thread creates an arrow referencing the Target.
    594   Arrow arrow;
    595   arrow.target = target->AsWeakPtr();
    596 
    597   // Background thread tries to delete target, binding the object to the thread.
    598   BackgroundThread background;
    599   background.Start();
    600   background.DeleteTarget(target.release());
    601 
    602   // Main thread attempts to dereference the target, violating thread binding.
    603   ASSERT_DEATH(arrow.target.get(), "");
    604 }
    605 
    606 #endif
    607 
    608 }  // namespace base
    609