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   // Test that the factory can create new weak pointers after a
    282   // InvalidateWeakPtrs call, and they remain valid until the next
    283   // InvalidateWeakPtrs call.
    284   WeakPtr<int> ptr2 = factory.GetWeakPtr();
    285   EXPECT_EQ(&data, ptr2.get());
    286   EXPECT_TRUE(factory.HasWeakPtrs());
    287   factory.InvalidateWeakPtrs();
    288   EXPECT_EQ(NULL, ptr2.get());
    289   EXPECT_FALSE(factory.HasWeakPtrs());
    290 }
    291 
    292 TEST(WeakPtrTest, HasWeakPtrs) {
    293   int data;
    294   WeakPtrFactory<int> factory(&data);
    295   {
    296     WeakPtr<int> ptr = factory.GetWeakPtr();
    297     EXPECT_TRUE(factory.HasWeakPtrs());
    298   }
    299   EXPECT_FALSE(factory.HasWeakPtrs());
    300 }
    301 
    302 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
    303   // Test that it is OK to create an object that supports WeakPtr on one thread,
    304   // but use it on another.  This tests that we do not trip runtime checks that
    305   // ensure that a WeakPtr is not used by multiple threads.
    306   scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
    307   WeakPtr<Target> weak_ptr = target->AsWeakPtr();
    308   EXPECT_EQ(target.get(), weak_ptr.get());
    309 }
    310 
    311 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
    312   // Test that it is OK to create an object that has a WeakPtr member on one
    313   // thread, but use it on another.  This tests that we do not trip runtime
    314   // checks that ensure that a WeakPtr is not used by multiple threads.
    315   scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
    316   Target target;
    317   arrow->target = target.AsWeakPtr();
    318   EXPECT_EQ(&target, arrow->target.get());
    319 }
    320 
    321 TEST(WeakPtrTest, MoveOwnershipImplicitly) {
    322   // Move object ownership to another thread by releasing all weak pointers
    323   // on the original thread first, and then establish WeakPtr on a different
    324   // thread.
    325   BackgroundThread background;
    326   background.Start();
    327 
    328   Target* target = new Target();
    329   {
    330     WeakPtr<Target> weak_ptr = target->AsWeakPtr();
    331     // Main thread deletes the WeakPtr, then the thread ownership of the
    332     // object can be implicitly moved.
    333   }
    334   Arrow* arrow;
    335 
    336   // Background thread creates WeakPtr(and implicitly owns the object).
    337   background.CreateArrowFromTarget(&arrow, target);
    338   EXPECT_EQ(background.DeRef(arrow), target);
    339 
    340   {
    341     // Main thread creates another WeakPtr, but this does not trigger implicitly
    342     // thread ownership move.
    343     Arrow arrow;
    344     arrow.target = target->AsWeakPtr();
    345 
    346     // The new WeakPtr is owned by background thread.
    347     EXPECT_EQ(target, background.DeRef(&arrow));
    348   }
    349 
    350   // Target can only be deleted on background thread.
    351   background.DeleteTarget(target);
    352   background.DeleteArrow(arrow);
    353 }
    354 
    355 TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
    356   BackgroundThread background;
    357   background.Start();
    358 
    359   Arrow* arrow;
    360   {
    361     Target target;
    362     // Background thread creates WeakPtr.
    363     background.CreateArrowFromTarget(&arrow, &target);
    364 
    365     // Bind to background thread.
    366     EXPECT_EQ(&target, background.DeRef(arrow));
    367 
    368     // Release the only WeakPtr.
    369     arrow->target.reset();
    370 
    371     // Now we should be able to create a new reference from this thread.
    372     arrow->target = target.AsWeakPtr();
    373 
    374     // Re-bind to main thread.
    375     EXPECT_EQ(&target, arrow->target.get());
    376 
    377     // And the main thread can now delete the target.
    378   }
    379 
    380   delete arrow;
    381 }
    382 
    383 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
    384   BackgroundThread background;
    385   background.Start();
    386 
    387   Arrow arrow;
    388   scoped_ptr<TargetWithFactory> target(new TargetWithFactory);
    389 
    390   // Bind to main thread.
    391   arrow.target = target->factory.GetWeakPtr();
    392   EXPECT_EQ(target.get(), arrow.target.get());
    393 
    394   target->factory.InvalidateWeakPtrs();
    395   EXPECT_EQ(NULL, arrow.target.get());
    396 
    397   arrow.target = target->factory.GetWeakPtr();
    398   // Re-bind to background thread.
    399   EXPECT_EQ(target.get(), background.DeRef(&arrow));
    400 
    401   // And the background thread can now delete the target.
    402   background.DeleteTarget(target.release());
    403 }
    404 
    405 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
    406   // Originating thread has a WeakPtr that outlives others.
    407   // - Main thread creates a WeakPtr
    408   // - Background thread creates a WeakPtr copy from the one in main thread
    409   // - Destruct the WeakPtr on background thread
    410   // - Destruct the WeakPtr on main thread
    411   BackgroundThread background;
    412   background.Start();
    413 
    414   Target target;
    415   Arrow arrow;
    416   arrow.target = target.AsWeakPtr();
    417 
    418   Arrow* arrow_copy;
    419   background.CreateArrowFromArrow(&arrow_copy, &arrow);
    420   EXPECT_EQ(arrow_copy->target.get(), &target);
    421   background.DeleteArrow(arrow_copy);
    422 }
    423 
    424 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
    425   // Originating thread drops all references before another thread.
    426   // - Main thread creates a WeakPtr and passes copy to background thread
    427   // - Destruct the pointer on main thread
    428   // - Destruct the pointer on background thread
    429   BackgroundThread background;
    430   background.Start();
    431 
    432   Target target;
    433   Arrow* arrow_copy;
    434   {
    435     Arrow arrow;
    436     arrow.target = target.AsWeakPtr();
    437     background.CreateArrowFromArrow(&arrow_copy, &arrow);
    438   }
    439   EXPECT_EQ(arrow_copy->target.get(), &target);
    440   background.DeleteArrow(arrow_copy);
    441 }
    442 
    443 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
    444   // Originating thread invalidates WeakPtrs while its held by other thread.
    445   // - Main thread creates WeakPtr and passes Copy to background thread
    446   // - Object gets destroyed on main thread
    447   //   (invalidates WeakPtr on background thread)
    448   // - WeakPtr gets destroyed on Thread B
    449   BackgroundThread background;
    450   background.Start();
    451   Arrow* arrow_copy;
    452   {
    453     Target target;
    454     Arrow arrow;
    455     arrow.target = target.AsWeakPtr();
    456     background.CreateArrowFromArrow(&arrow_copy, &arrow);
    457   }
    458   EXPECT_EQ(NULL, arrow_copy->target.get());
    459   background.DeleteArrow(arrow_copy);
    460 }
    461 
    462 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
    463   // Main thread creates a Target object.
    464   Target target;
    465   // Main thread creates an arrow referencing the Target.
    466   Arrow *arrow = new Arrow();
    467   arrow->target = target.AsWeakPtr();
    468 
    469   // Background can copy and assign arrow (as well as the WeakPtr inside).
    470   BackgroundThread background;
    471   background.Start();
    472   background.CopyAndAssignArrow(arrow);
    473   background.DeleteArrow(arrow);
    474 }
    475 
    476 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
    477   // Main thread creates a Target object.
    478   Target target;
    479   // Main thread creates an arrow referencing the Target.
    480   Arrow *arrow = new Arrow();
    481   arrow->target = target.AsWeakPtr();
    482 
    483   // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
    484   BackgroundThread background;
    485   background.Start();
    486   background.CopyAndAssignArrowBase(arrow);
    487   background.DeleteArrow(arrow);
    488 }
    489 
    490 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
    491   // Main thread creates a Target object.
    492   Target target;
    493   // Main thread creates an arrow referencing the Target.
    494   Arrow* arrow = new Arrow();
    495   arrow->target = target.AsWeakPtr();
    496 
    497   // Background can delete arrow (as well as the WeakPtr inside).
    498   BackgroundThread background;
    499   background.Start();
    500   background.DeleteArrow(arrow);
    501 }
    502 
    503 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST
    504 
    505 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
    506   // The default style "fast" does not support multi-threaded tests
    507   // (introduces deadlock on Linux).
    508   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    509 
    510   BackgroundThread background;
    511   background.Start();
    512 
    513   // Main thread creates a Target object.
    514   Target target;
    515   // Main thread creates an arrow referencing the Target.
    516   Arrow arrow;
    517   arrow.target = target.AsWeakPtr();
    518 
    519   // Background copies the WeakPtr.
    520   Arrow* arrow_copy;
    521   background.CreateArrowFromArrow(&arrow_copy, &arrow);
    522 
    523   // The copy is still bound to main thread so I can deref.
    524   EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
    525 
    526   // Although background thread created the copy, it can not deref the copied
    527   // WeakPtr.
    528   ASSERT_DEATH(background.DeRef(arrow_copy), "");
    529 
    530   background.DeleteArrow(arrow_copy);
    531 }
    532 
    533 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
    534   // The default style "fast" does not support multi-threaded tests
    535   // (introduces deadlock on Linux).
    536   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    537 
    538   // Main thread creates a Target object.
    539   Target target;
    540 
    541   // Main thread creates an arrow referencing the Target (so target's
    542   // thread ownership can not be implicitly moved).
    543   Arrow arrow;
    544   arrow.target = target.AsWeakPtr();
    545   arrow.target.get();
    546 
    547   // Background thread tries to deref target, which violates thread ownership.
    548   BackgroundThread background;
    549   background.Start();
    550   ASSERT_DEATH(background.DeRef(&arrow), "");
    551 }
    552 
    553 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
    554   // The default style "fast" does not support multi-threaded tests
    555   // (introduces deadlock on Linux).
    556   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    557 
    558   scoped_ptr<Target> target(new Target());
    559 
    560   // Main thread creates an arrow referencing the Target.
    561   Arrow arrow;
    562   arrow.target = target->AsWeakPtr();
    563 
    564   // Background thread tries to deref target, binding it to the thread.
    565   BackgroundThread background;
    566   background.Start();
    567   background.DeRef(&arrow);
    568 
    569   // Main thread deletes Target, violating thread binding.
    570   ASSERT_DEATH(target.reset(), "");
    571 
    572   // |target.reset()| died so |target| still holds the object, so we
    573   // must pass it to the background thread to teardown.
    574   background.DeleteTarget(target.release());
    575 }
    576 
    577 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
    578   // The default style "fast" does not support multi-threaded tests
    579   // (introduces deadlock on Linux).
    580   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    581 
    582   scoped_ptr<Target> target(new Target());
    583 
    584   // Main thread creates an arrow referencing the Target, and references it, so
    585   // that it becomes bound to the thread.
    586   Arrow arrow;
    587   arrow.target = target->AsWeakPtr();
    588   arrow.target.get();
    589 
    590   // Background thread tries to delete target, volating thread binding.
    591   BackgroundThread background;
    592   background.Start();
    593   ASSERT_DEATH(background.DeleteTarget(target.release()), "");
    594 }
    595 
    596 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
    597   // The default style "fast" does not support multi-threaded tests
    598   // (introduces deadlock on Linux).
    599   ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    600 
    601   scoped_ptr<Target> target(new Target());
    602 
    603   // Main thread creates an arrow referencing the Target.
    604   Arrow arrow;
    605   arrow.target = target->AsWeakPtr();
    606 
    607   // Background thread tries to delete target, binding the object to the thread.
    608   BackgroundThread background;
    609   background.Start();
    610   background.DeleteTarget(target.release());
    611 
    612   // Main thread attempts to dereference the target, violating thread binding.
    613   ASSERT_DEATH(arrow.target.get(), "");
    614 }
    615 
    616 #endif
    617 
    618 }  // namespace base
    619