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