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 794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory> 8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <string> 9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/bind.h" 1194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/debug/leak_annotations.h" 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/location.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 2194ffa55491333f3dcc701befd0d2652922916d99Luis Hector ChavezWeakPtr<int> PassThru(WeakPtr<int> ptr) { 2294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return ptr; 2394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez} 2494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erattemplate <class T> 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass OffThreadObjectCreator { 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static T* NewObject() { 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat T* result; 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Thread creator_thread("creator_thread"); 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat creator_thread.Start(); 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat creator_thread.task_runner()->PostTask( 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FROM_HERE, base::Bind(OffThreadObjectCreator::CreateObject, &result)); 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(result); // We synchronized on thread destruction above. 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return result; 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private: 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void CreateObject(T** result) { 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *result = new T; 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct Base { 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string member; 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct Derived : public Base {}; 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct TargetBase {}; 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct Target : public TargetBase, public SupportsWeakPtr<Target> { 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat virtual ~Target() {} 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct DerivedTarget : public Target {}; 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct Arrow { 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<Target> target; 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstruct TargetWithFactory : public Target { 59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat TargetWithFactory() : factory(this) {} 60b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<Target> factory; 61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Helper class to create and destroy weak pointer copies 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// and delete objects on a background thread. 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass BackgroundThread : public Thread { 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public: 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread() : Thread("owner_thread") {} 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ~BackgroundThread() override { Stop(); } 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void CreateArrowFromTarget(Arrow** arrow, Target* target) { 720c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL, 730c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent::InitialState::NOT_SIGNALED); 74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat task_runner()->PostTask( 75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FROM_HERE, base::Bind(&BackgroundThread::DoCreateArrowFromTarget, arrow, 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target, &completion)); 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion.Wait(); 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) { 810c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL, 820c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent::InitialState::NOT_SIGNALED); 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat task_runner()->PostTask( 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FROM_HERE, base::Bind(&BackgroundThread::DoCreateArrowFromArrow, arrow, 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat other, &completion)); 86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion.Wait(); 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void DeleteTarget(Target* object) { 900c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL, 910c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent::InitialState::NOT_SIGNALED); 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat task_runner()->PostTask( 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FROM_HERE, 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion)); 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion.Wait(); 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void CopyAndAssignArrow(Arrow* object) { 990c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL, 1000c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent::InitialState::NOT_SIGNALED); 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat task_runner()->PostTask( 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FROM_HERE, base::Bind(&BackgroundThread::DoCopyAndAssignArrow, object, 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat &completion)); 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion.Wait(); 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void CopyAndAssignArrowBase(Arrow* object) { 1080c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL, 1090c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent::InitialState::NOT_SIGNALED); 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat task_runner()->PostTask( 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FROM_HERE, base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase, 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat object, &completion)); 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion.Wait(); 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat void DeleteArrow(Arrow* object) { 1170c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL, 1180c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent::InitialState::NOT_SIGNALED); 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat task_runner()->PostTask( 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat FROM_HERE, 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion)); 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion.Wait(); 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target* DeRef(const Arrow* arrow) { 1260c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL, 1270c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WaitableEvent::InitialState::NOT_SIGNALED); 12894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez Target* result = nullptr; 129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat task_runner()->PostTask(FROM_HERE, base::Bind(&BackgroundThread::DoDeRef, 130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow, &result, &completion)); 131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion.Wait(); 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return result; 133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat protected: 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void DoCreateArrowFromArrow(Arrow** arrow, 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const Arrow* other, 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WaitableEvent* completion) { 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *arrow = new Arrow; 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat **arrow = *other; 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion->Signal(); 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void DoCreateArrowFromTarget(Arrow** arrow, 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target* target, 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WaitableEvent* completion) { 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *arrow = new Arrow; 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat (*arrow)->target = target->AsWeakPtr(); 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion->Signal(); 150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void DoDeRef(const Arrow* arrow, 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target** result, 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WaitableEvent* completion) { 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *result = arrow->target.get(); 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion->Signal(); 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void DoDeleteTarget(Target* object, WaitableEvent* completion) { 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat delete object; 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion->Signal(); 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) { 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Copy constructor. 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow a = *object; 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Assignment operator. 168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat *object = a; 169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion->Signal(); 170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void DoCopyAndAssignArrowBase( 173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow* object, 174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WaitableEvent* completion) { 175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Copy constructor. 176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<TargetBase> b = object->target; 177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Assignment operator. 178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<TargetBase> c; 179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat c = object->target; 180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion->Signal(); 181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) { 184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat delete object; 185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat completion->Signal(); 186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}; 188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, Basic) { 192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int data; 193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<int> factory(&data); 194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> ptr = factory.GetWeakPtr(); 195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&data, ptr.get()); 196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, Comparison) { 199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int data; 200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<int> factory(&data); 201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> ptr = factory.GetWeakPtr(); 202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> ptr2 = ptr; 203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(ptr.get(), ptr2.get()); 204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 2060c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector ChavezTEST(WeakPtrFactoryTest, Move) { 2070c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez int data; 2080c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WeakPtrFactory<int> factory(&data); 2090c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WeakPtr<int> ptr = factory.GetWeakPtr(); 2100c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WeakPtr<int> ptr2 = factory.GetWeakPtr(); 2110c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WeakPtr<int> ptr3 = std::move(ptr2); 2120c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez EXPECT_NE(ptr.get(), ptr2.get()); 2130c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez EXPECT_EQ(ptr.get(), ptr3.get()); 2140c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez} 2150c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, OutOfScope) { 217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> ptr; 21894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, ptr.get()); 219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int data; 221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<int> factory(&data); 222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ptr = factory.GetWeakPtr(); 223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 22494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, ptr.get()); 225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, Multiple) { 228b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> a, b; 229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int data; 231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<int> factory(&data); 232b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat a = factory.GetWeakPtr(); 233b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat b = factory.GetWeakPtr(); 234b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&data, a.get()); 235b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&data, b.get()); 236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 23794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, a.get()); 23894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, b.get()); 239b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 240b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 241b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, MultipleStaged) { 242b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> a; 243b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 244b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int data; 245b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<int> factory(&data); 246b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat a = factory.GetWeakPtr(); 247b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 248b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> b = factory.GetWeakPtr(); 249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 25094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_NE(nullptr, a.get()); 251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 25294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, a.get()); 253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, Dereference) { 256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Base data; 257b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat data.member = "123456"; 258b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<Base> factory(&data); 259b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<Base> ptr = factory.GetWeakPtr(); 260b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&data, ptr.get()); 261b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(data.member, (*ptr).member); 262b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(data.member, ptr->member); 263b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 264b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 265b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrFactoryTest, UpCast) { 266b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Derived data; 267b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<Derived> factory(&data); 268b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<Base> ptr = factory.GetWeakPtr(); 269b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ptr = factory.GetWeakPtr(); 270b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(ptr.get(), &data); 271b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 272b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 27394ffa55491333f3dcc701befd0d2652922916d99Luis Hector ChavezTEST(WeakPtrTest, ConstructFromNullptr) { 27494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez WeakPtr<int> ptr = PassThru(nullptr); 27594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, ptr.get()); 27694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez} 27794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 278b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, SupportsWeakPtr) { 279b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 280b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<Target> ptr = target.AsWeakPtr(); 281b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&target, ptr.get()); 282b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 283b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 284b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, DerivedTarget) { 285b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DerivedTarget target; 286b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target); 287b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&target, ptr.get()); 288b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 289b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 29045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex VakulenkoTEST(WeakPtrFactoryTest, BooleanTesting) { 29145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko int data; 29245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko WeakPtrFactory<int> factory(&data); 29345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 29445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr(); 29545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(ptr_to_an_instance); 29645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(!ptr_to_an_instance); 29745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 29845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (ptr_to_an_instance) { 29945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } else { 30045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ADD_FAILURE() << "Pointer to an instance should result in true."; 30145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 30245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 30345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (!ptr_to_an_instance) { // check for operator!(). 30445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ADD_FAILURE() << "Pointer to an instance should result in !x being false."; 30545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 30645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 30745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko WeakPtr<int> null_ptr; 30845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_FALSE(null_ptr); 30945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko EXPECT_TRUE(!null_ptr); 31045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 31145779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (null_ptr) { 31245779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ADD_FAILURE() << "Null pointer should result in false."; 31345779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 31445779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 31545779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko if (!null_ptr) { // check for operator!(). 31645779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } else { 31745779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko ADD_FAILURE() << "Null pointer should result in !x being true."; 31845779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko } 31945779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko} 32045779228f8c9e40851cfd23f727e2bd8ffdd4714Alex Vakulenko 3210c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector ChavezTEST(WeakPtrFactoryTest, ComparisonToNull) { 3220c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez int data; 3230c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WeakPtrFactory<int> factory(&data); 3240c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 3250c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr(); 3260c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez EXPECT_NE(nullptr, ptr_to_an_instance); 3270c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez EXPECT_NE(ptr_to_an_instance, nullptr); 3280c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 3290c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez WeakPtr<int> null_ptr; 3300c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez EXPECT_EQ(null_ptr, nullptr); 3310c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez EXPECT_EQ(nullptr, null_ptr); 3320c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez} 3330c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez 334b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, InvalidateWeakPtrs) { 335b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int data; 336b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<int> factory(&data); 337b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> ptr = factory.GetWeakPtr(); 338b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&data, ptr.get()); 339b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(factory.HasWeakPtrs()); 340b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat factory.InvalidateWeakPtrs(); 34194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, ptr.get()); 342b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(factory.HasWeakPtrs()); 343b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 344b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Test that the factory can create new weak pointers after a 345b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // InvalidateWeakPtrs call, and they remain valid until the next 346b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // InvalidateWeakPtrs call. 347b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> ptr2 = factory.GetWeakPtr(); 348b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&data, ptr2.get()); 349b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(factory.HasWeakPtrs()); 350b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat factory.InvalidateWeakPtrs(); 35194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, ptr2.get()); 352b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(factory.HasWeakPtrs()); 353b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 354b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 355b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, HasWeakPtrs) { 356b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int data; 357b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtrFactory<int> factory(&data); 358b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 359b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<int> ptr = factory.GetWeakPtr(); 360b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_TRUE(factory.HasWeakPtrs()); 361b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 362b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_FALSE(factory.HasWeakPtrs()); 363b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 364b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 365b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) { 366b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Test that it is OK to create an object that supports WeakPtr on one thread, 367b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // but use it on another. This tests that we do not trip runtime checks that 368b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // ensure that a WeakPtr is not used by multiple threads. 36994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject()); 370b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<Target> weak_ptr = target->AsWeakPtr(); 371b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(target.get(), weak_ptr.get()); 372b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 373b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 374b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) { 375b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Test that it is OK to create an object that has a WeakPtr member on one 376b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // thread, but use it on another. This tests that we do not trip runtime 377b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // checks that ensure that a WeakPtr is not used by multiple threads. 37894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject()); 379b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 380b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow->target = target.AsWeakPtr(); 381b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&target, arrow->target.get()); 382b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 383b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 384b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, MoveOwnershipImplicitly) { 385b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Move object ownership to another thread by releasing all weak pointers 386b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // on the original thread first, and then establish WeakPtr on a different 387b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // thread. 388b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 389b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 390b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 391b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target* target = new Target(); 392b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 393b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat WeakPtr<Target> weak_ptr = target->AsWeakPtr(); 394b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread deletes the WeakPtr, then the thread ownership of the 395b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // object can be implicitly moved. 396b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 397b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow* arrow; 398b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 399b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background thread creates WeakPtr(and implicitly owns the object). 400b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.CreateArrowFromTarget(&arrow, target); 401b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(background.DeRef(arrow), target); 402b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 403b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 404b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates another WeakPtr, but this does not trigger implicitly 405b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // thread ownership move. 406b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 407b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target->AsWeakPtr(); 408b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 409b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The new WeakPtr is owned by background thread. 410b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(target, background.DeRef(&arrow)); 411b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 412b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 413b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Target can only be deleted on background thread. 414b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteTarget(target); 415b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteArrow(arrow); 416b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 417b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 418b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) { 419b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 420b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 421b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 422b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow* arrow; 423b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 424b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 425b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background thread creates WeakPtr. 426b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.CreateArrowFromTarget(&arrow, &target); 427b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 428b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Bind to background thread. 429b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&target, background.DeRef(arrow)); 430b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 431b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Release the only WeakPtr. 432b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow->target.reset(); 433b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 434b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Now we should be able to create a new reference from this thread. 435b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow->target = target.AsWeakPtr(); 436b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 437b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Re-bind to main thread. 438b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(&target, arrow->target.get()); 439b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 440b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // And the main thread can now delete the target. 441b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 442b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 443b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat delete arrow; 444b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 445b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 446b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, MoveOwnershipAfterInvalidate) { 447b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 448b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 449b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 450b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 45194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<TargetWithFactory> target(new TargetWithFactory); 452b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 453b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Bind to main thread. 454b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target->factory.GetWeakPtr(); 455b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(target.get(), arrow.target.get()); 456b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 457b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat target->factory.InvalidateWeakPtrs(); 45894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, arrow.target.get()); 459b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 460b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target->factory.GetWeakPtr(); 461b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Re-bind to background thread. 462b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(target.get(), background.DeRef(&arrow)); 463b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 464b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // And the background thread can now delete the target. 465b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteTarget(target.release()); 466b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 467b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 468b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) { 469b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Originating thread has a WeakPtr that outlives others. 470b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - Main thread creates a WeakPtr 471b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - Background thread creates a WeakPtr copy from the one in main thread 472b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - Destruct the WeakPtr on background thread 473b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - Destruct the WeakPtr on main thread 474b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 475b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 476b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 477b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 478b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 479b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target.AsWeakPtr(); 480b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 481b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow* arrow_copy; 482b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.CreateArrowFromArrow(&arrow_copy, &arrow); 483b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(arrow_copy->target.get(), &target); 484b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteArrow(arrow_copy); 485b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 486b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 487b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) { 488b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Originating thread drops all references before another thread. 489b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - Main thread creates a WeakPtr and passes copy to background thread 490b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - Destruct the pointer on main thread 491b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - Destruct the pointer on background thread 492b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 493b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 494b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 495b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 496b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow* arrow_copy; 497b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 498b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 499b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target.AsWeakPtr(); 500b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.CreateArrowFromArrow(&arrow_copy, &arrow); 501b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 502b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(arrow_copy->target.get(), &target); 503b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteArrow(arrow_copy); 504b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 505b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 506b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, OwnerThreadDeletesObject) { 507b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Originating thread invalidates WeakPtrs while its held by other thread. 508b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - Main thread creates WeakPtr and passes Copy to background thread 509b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - Object gets destroyed on main thread 510b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // (invalidates WeakPtr on background thread) 511b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - WeakPtr gets destroyed on Thread B 512b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 513b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 514b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow* arrow_copy; 515b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat { 516b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 517b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 518b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target.AsWeakPtr(); 519b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.CreateArrowFromArrow(&arrow_copy, &arrow); 520b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 52194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez EXPECT_EQ(nullptr, arrow_copy->target.get()); 522b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteArrow(arrow_copy); 523b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 524b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 525b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) { 526b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates a Target object. 527b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 528b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates an arrow referencing the Target. 529b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow *arrow = new Arrow(); 530b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow->target = target.AsWeakPtr(); 531b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 532b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background can copy and assign arrow (as well as the WeakPtr inside). 533b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 534b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 535b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.CopyAndAssignArrow(arrow); 536b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteArrow(arrow); 537b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 538b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 539b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) { 540b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates a Target object. 541b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 542b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates an arrow referencing the Target. 543b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow *arrow = new Arrow(); 544b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow->target = target.AsWeakPtr(); 545b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 546b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background can copy and assign arrow's WeakPtr to a base class WeakPtr. 547b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 548b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 549b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.CopyAndAssignArrowBase(arrow); 550b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteArrow(arrow); 551b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 552b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 553b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) { 554b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates a Target object. 555b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 556b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates an arrow referencing the Target. 557b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow* arrow = new Arrow(); 558b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow->target = target.AsWeakPtr(); 559b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 560b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background can delete arrow (as well as the WeakPtr inside). 561b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 562b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 563b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteArrow(arrow); 564b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 565b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 566b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST 567b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 568b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) { 569b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The default style "fast" does not support multi-threaded tests 570b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // (introduces deadlock on Linux). 571b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 572b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 573b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 574b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 575b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 576b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates a Target object. 577b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 578b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates an arrow referencing the Target. 579b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 580b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target.AsWeakPtr(); 581b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 582b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background copies the WeakPtr. 583b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow* arrow_copy; 584b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.CreateArrowFromArrow(&arrow_copy, &arrow); 585b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 586b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The copy is still bound to main thread so I can deref. 587b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat EXPECT_EQ(arrow.target.get(), arrow_copy->target.get()); 588b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 589b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Although background thread created the copy, it can not deref the copied 590b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // WeakPtr. 591b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_DEATH(background.DeRef(arrow_copy), ""); 592b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 593b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteArrow(arrow_copy); 594b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 595b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 596b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) { 597b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The default style "fast" does not support multi-threaded tests 598b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // (introduces deadlock on Linux). 599b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 600b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 601b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates a Target object. 602b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Target target; 603b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 604b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates an arrow referencing the Target (so target's 605b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // thread ownership can not be implicitly moved). 606b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 607b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target.AsWeakPtr(); 608b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target.get(); 609b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 610b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background thread tries to deref target, which violates thread ownership. 611b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 612b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 613b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_DEATH(background.DeRef(&arrow), ""); 614b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 615b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 616b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) { 617b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The default style "fast" does not support multi-threaded tests 618b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // (introduces deadlock on Linux). 619b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 620b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 62194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<Target> target(new Target()); 622b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 623b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates an arrow referencing the Target. 624b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 625b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target->AsWeakPtr(); 626b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 627b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background thread tries to deref target, binding it to the thread. 628b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 629b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 630b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeRef(&arrow); 631b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 632b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread deletes Target, violating thread binding. 633b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_DEATH(target.reset(), ""); 634b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 635b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // |target.reset()| died so |target| still holds the object, so we 636b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // must pass it to the background thread to teardown. 637b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteTarget(target.release()); 638b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 639b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 640b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) { 641b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The default style "fast" does not support multi-threaded tests 642b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // (introduces deadlock on Linux). 643b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 644b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 64594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<Target> target(new Target()); 646b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 647b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates an arrow referencing the Target, and references it, so 648b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // that it becomes bound to the thread. 649b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 650b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target->AsWeakPtr(); 651b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target.get(); 652b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 653b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background thread tries to delete target, volating thread binding. 654b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 655b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 656b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_DEATH(background.DeleteTarget(target.release()), ""); 657b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 658b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 659b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) { 660b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The default style "fast" does not support multi-threaded tests 661b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // (introduces deadlock on Linux). 662b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 663b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 66494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<Target> target(new Target()); 665b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 666b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread creates an arrow referencing the Target. 667b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Arrow arrow; 668b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat arrow.target = target->AsWeakPtr(); 669b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 670b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Background thread tries to delete target, binding the object to the thread. 671b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat BackgroundThread background; 672b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.Start(); 673b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat background.DeleteTarget(target.release()); 674b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 675b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Main thread attempts to dereference the target, violating thread binding. 676b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ASSERT_DEATH(arrow.target.get(), ""); 677b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 678b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 679b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif 680b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 681b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 682