15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/debug/leak_annotations.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T> 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OffThreadObjectCreator { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static T* NewObject() { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T* result; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Thread creator_thread("creator_thread"); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) creator_thread.Start(); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) creator_thread.message_loop()->PostTask( 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(OffThreadObjectCreator::CreateObject, &result)); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(result); // We synchronized on thread destruction above. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void CreateObject(T** result) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = new T; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Base { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string member; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct Derived : public Base {}; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct TargetBase {}; 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct Target : public TargetBase, public SupportsWeakPtr<Target> { 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~Target() {} 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct DerivedTarget : public Target {}; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Arrow { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<Target> target; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)struct TargetWithFactory : public Target { 55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) TargetWithFactory() : factory(this) {} 56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) WeakPtrFactory<Target> factory; 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class to create and destroy weak pointer copies 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and delete objects on a background thread. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BackgroundThread : public Thread { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread() : Thread("owner_thread") {} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~BackgroundThread() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CreateArrowFromTarget(Arrow** arrow, Target* target) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent completion(true, false); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop()->PostTask( 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BackgroundThread::DoCreateArrowFromTarget, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow, target, &completion)); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion.Wait(); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent completion(true, false); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop()->PostTask( 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BackgroundThread::DoCreateArrowFromArrow, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow, other, &completion)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion.Wait(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DeleteTarget(Target* object) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent completion(true, false); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop()->PostTask( 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion)); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion.Wait(); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CopyAndAssignArrow(Arrow* object) { 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitableEvent completion(true, false); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop()->PostTask( 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&BackgroundThread::DoCopyAndAssignArrow, 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) object, &completion)); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) completion.Wait(); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void CopyAndAssignArrowBase(Arrow* object) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitableEvent completion(true, false); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) message_loop()->PostTask( 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FROM_HERE, 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase, 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) object, &completion)); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) completion.Wait(); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DeleteArrow(Arrow* object) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent completion(true, false); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop()->PostTask( 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion)); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion.Wait(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target* DeRef(const Arrow* arrow) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent completion(true, false); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target* result = NULL; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_loop()->PostTask( 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion)); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion.Wait(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void DoCreateArrowFromArrow(Arrow** arrow, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Arrow* other, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* completion) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *arrow = new Arrow; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) **arrow = *other; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion->Signal(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void DoCreateArrowFromTarget(Arrow** arrow, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target* target, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* completion) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *arrow = new Arrow; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*arrow)->target = target->AsWeakPtr(); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion->Signal(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void DoDeRef(const Arrow* arrow, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target** result, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitableEvent* completion) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = arrow->target.get(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion->Signal(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void DoDeleteTarget(Target* object, WaitableEvent* completion) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete object; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion->Signal(); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) { 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy constructor. 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Arrow a = *object; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Assignment operator. 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *object = a; 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) completion->Signal(); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static void DoCopyAndAssignArrowBase( 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Arrow* object, 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WaitableEvent* completion) { 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Copy constructor. 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WeakPtr<TargetBase> b = object->target; 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Assignment operator. 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WeakPtr<TargetBase> c; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) c = object->target; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) completion->Signal(); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete object; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion->Signal(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrFactoryTest, Basic) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtrFactory<int> factory(&data); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<int> ptr = factory.GetWeakPtr(); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&data, ptr.get()); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrFactoryTest, Comparison) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtrFactory<int> factory(&data); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<int> ptr = factory.GetWeakPtr(); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<int> ptr2 = ptr; 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ(ptr.get(), ptr2.get()); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrFactoryTest, OutOfScope) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<int> ptr; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, ptr.get()); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtrFactory<int> factory(&data); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = factory.GetWeakPtr(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, ptr.get()); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrFactoryTest, Multiple) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<int> a, b; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtrFactory<int> factory(&data); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a = factory.GetWeakPtr(); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) b = factory.GetWeakPtr(); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&data, a.get()); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&data, b.get()); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, a.get()); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, b.get()); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrFactoryTest, MultipleStaged) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<int> a; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtrFactory<int> factory(&data); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a = factory.GetWeakPtr(); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<int> b = factory.GetWeakPtr(); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NULL != a.get()); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, a.get()); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrFactoryTest, Dereference) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Base data; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.member = "123456"; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtrFactory<Base> factory(&data); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<Base> ptr = factory.GetWeakPtr(); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&data, ptr.get()); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(data.member, (*ptr).member); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(data.member, ptr->member); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrFactoryTest, UpCast) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Derived data; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtrFactory<Derived> factory(&data); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<Base> ptr = factory.GetWeakPtr(); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr = factory.GetWeakPtr(); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(ptr.get(), &data); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, SupportsWeakPtr) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target target; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<Target> ptr = target.AsWeakPtr(); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&target, ptr.get()); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, DerivedTarget) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DerivedTarget target; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&target, ptr.get()); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, InvalidateWeakPtrs) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtrFactory<int> factory(&data); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<int> ptr = factory.GetWeakPtr(); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&data, ptr.get()); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(factory.HasWeakPtrs()); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) factory.InvalidateWeakPtrs(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, ptr.get()); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(factory.HasWeakPtrs()); 280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Test that the factory can create new weak pointers after a 282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // InvalidateWeakPtrs call, and they remain valid until the next 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // InvalidateWeakPtrs call. 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WeakPtr<int> ptr2 = factory.GetWeakPtr(); 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(&data, ptr2.get()); 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_TRUE(factory.HasWeakPtrs()); 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch factory.InvalidateWeakPtrs(); 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(NULL, ptr2.get()); 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_FALSE(factory.HasWeakPtrs()); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, HasWeakPtrs) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtrFactory<int> factory(&data); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<int> ptr = factory.GetWeakPtr(); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(factory.HasWeakPtrs()); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(factory.HasWeakPtrs()); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that it is OK to create an object that supports WeakPtr on one thread, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but use it on another. This tests that we do not trip runtime checks that 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ensure that a WeakPtr is not used by multiple threads. 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject()); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<Target> weak_ptr = target->AsWeakPtr(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(target.get(), weak_ptr.get()); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that it is OK to create an object that has a WeakPtr member on one 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread, but use it on another. This tests that we do not trip runtime 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // checks that ensure that a WeakPtr is not used by multiple threads. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject()); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target target; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow->target = target.AsWeakPtr(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&target, arrow->target.get()); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, MoveOwnershipImplicitly) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move object ownership to another thread by releasing all weak pointers 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on the original thread first, and then establish WeakPtr on a different 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread background; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.Start(); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target* target = new Target(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WeakPtr<Target> weak_ptr = target->AsWeakPtr(); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Main thread deletes the WeakPtr, then the thread ownership of the 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // object can be implicitly moved. 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow* arrow; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Background thread creates WeakPtr(and implicitly owns the object). 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.CreateArrowFromTarget(&arrow, target); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(background.DeRef(arrow), target); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Main thread creates another WeakPtr, but this does not trigger implicitly 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread ownership move. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow arrow; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow.target = target->AsWeakPtr(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The new WeakPtr is owned by background thread. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(target, background.DeRef(&arrow)); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Target can only be deleted on background thread. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.DeleteTarget(target); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.DeleteArrow(arrow); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) { 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread background; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.Start(); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow* arrow; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target target; 362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Background thread creates WeakPtr. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.CreateArrowFromTarget(&arrow, &target); 364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Bind to background thread. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&target, background.DeRef(arrow)); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Release the only WeakPtr. 369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) arrow->target.reset(); 370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Now we should be able to create a new reference from this thread. 372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) arrow->target = target.AsWeakPtr(); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Re-bind to main thread. 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(&target, arrow->target.get()); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // And the main thread can now delete the target. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 380a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) delete arrow; 381a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 382a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 383a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) { 384a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) BackgroundThread background; 385a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) background.Start(); 386a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 387a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Arrow arrow; 388a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) scoped_ptr<TargetWithFactory> target(new TargetWithFactory); 389a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 390a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Bind to main thread. 391a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) arrow.target = target->factory.GetWeakPtr(); 392a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(target.get(), arrow.target.get()); 393a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 394a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) target->factory.InvalidateWeakPtrs(); 395a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(NULL, arrow.target.get()); 396a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 397a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) arrow.target = target->factory.GetWeakPtr(); 398a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Re-bind to background thread. 399a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) EXPECT_EQ(target.get(), background.DeRef(&arrow)); 400a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 401a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // And the background thread can now delete the target. 402a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) background.DeleteTarget(target.release()); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Originating thread has a WeakPtr that outlives others. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Main thread creates a WeakPtr 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Background thread creates a WeakPtr copy from the one in main thread 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Destruct the WeakPtr on background thread 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Destruct the WeakPtr on main thread 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread background; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.Start(); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target target; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow arrow; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow.target = target.AsWeakPtr(); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow* arrow_copy; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.CreateArrowFromArrow(&arrow_copy, &arrow); 420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ(arrow_copy->target.get(), &target); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.DeleteArrow(arrow_copy); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Originating thread drops all references before another thread. 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Main thread creates a WeakPtr and passes copy to background thread 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Destruct the pointer on main thread 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Destruct the pointer on background thread 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread background; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.Start(); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target target; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow* arrow_copy; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow arrow; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow.target = target.AsWeakPtr(); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.CreateArrowFromArrow(&arrow_copy, &arrow); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) EXPECT_EQ(arrow_copy->target.get(), &target); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.DeleteArrow(arrow_copy); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, OwnerThreadDeletesObject) { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Originating thread invalidates WeakPtrs while its held by other thread. 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Main thread creates WeakPtr and passes Copy to background thread 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - Object gets destroyed on main thread 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (invalidates WeakPtr on background thread) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - WeakPtr gets destroyed on Thread B 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread background; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.Start(); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow* arrow_copy; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target target; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow arrow; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow.target = target.AsWeakPtr(); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.CreateArrowFromArrow(&arrow_copy, &arrow); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, arrow_copy->target.get()); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.DeleteArrow(arrow_copy); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) { 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Main thread creates a Target object. 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Target target; 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Main thread creates an arrow referencing the Target. 466868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Arrow *arrow = new Arrow(); 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) arrow->target = target.AsWeakPtr(); 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Background can copy and assign arrow (as well as the WeakPtr inside). 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BackgroundThread background; 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background.Start(); 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background.CopyAndAssignArrow(arrow); 473868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) background.DeleteArrow(arrow); 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) { 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Main thread creates a Target object. 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Target target; 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Main thread creates an arrow referencing the Target. 480868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Arrow *arrow = new Arrow(); 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) arrow->target = target.AsWeakPtr(); 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Background can copy and assign arrow's WeakPtr to a base class WeakPtr. 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BackgroundThread background; 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background.Start(); 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) background.CopyAndAssignArrowBase(arrow); 487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) background.DeleteArrow(arrow); 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Main thread creates a Target object. 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target target; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Main thread creates an arrow referencing the Target. 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow* arrow = new Arrow(); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow->target = target.AsWeakPtr(); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Background can delete arrow (as well as the WeakPtr inside). 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread background; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.Start(); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.DeleteArrow(arrow); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) { 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The default style "fast" does not support multi-threaded tests 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (introduces deadlock on Linux). 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread background; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.Start(); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Main thread creates a Target object. 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target target; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Main thread creates an arrow referencing the Target. 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow arrow; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow.target = target.AsWeakPtr(); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Background copies the WeakPtr. 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow* arrow_copy; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.CreateArrowFromArrow(&arrow_copy, &arrow); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The copy is still bound to main thread so I can deref. 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(arrow.target.get(), arrow_copy->target.get()); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Although background thread created the copy, it can not deref the copied 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WeakPtr. 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_DEATH(background.DeRef(arrow_copy), ""); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.DeleteArrow(arrow_copy); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 53390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The default style "fast" does not support multi-threaded tests 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (introduces deadlock on Linux). 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Main thread creates a Target object. 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Target target; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Main thread creates an arrow referencing the Target (so target's 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread ownership can not be implicitly moved). 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow arrow; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow.target = target.AsWeakPtr(); 54590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) arrow.target.get(); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Background thread tries to deref target, which violates thread ownership. 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread background; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.Start(); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_DEATH(background.DeRef(&arrow), ""); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) { 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The default style "fast" does not support multi-threaded tests 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (introduces deadlock on Linux). 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Target> target(new Target()); 55990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 56090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Main thread creates an arrow referencing the Target. 56190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Arrow arrow; 56290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) arrow.target = target->AsWeakPtr(); 56390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 56490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Background thread tries to deref target, binding it to the thread. 56590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BackgroundThread background; 56690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) background.Start(); 56790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) background.DeRef(&arrow); 56890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 56990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Main thread deletes Target, violating thread binding. 570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ASSERT_DEATH(target.reset(), ""); 571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // |target.reset()| died so |target| still holds the object, so we 573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // must pass it to the background thread to teardown. 574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) background.DeleteTarget(target.release()); 57590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 57690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 57790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) { 57890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The default style "fast" does not support multi-threaded tests 57990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // (introduces deadlock on Linux). 58090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 58190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 58290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<Target> target(new Target()); 58390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 58490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Main thread creates an arrow referencing the Target, and references it, so 58590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // that it becomes bound to the thread. 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Arrow arrow; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arrow.target = target->AsWeakPtr(); 58890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) arrow.target.get(); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 59090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Background thread tries to delete target, volating thread binding. 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BackgroundThread background; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) background.Start(); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_DEATH(background.DeleteTarget(target.release()), ""); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 59690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) { 59790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The default style "fast" does not support multi-threaded tests 59890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // (introduces deadlock on Linux). 59990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 60090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 60190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<Target> target(new Target()); 60290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 60390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Main thread creates an arrow referencing the Target. 60490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Arrow arrow; 60590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) arrow.target = target->AsWeakPtr(); 60690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 60790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Background thread tries to delete target, binding the object to the thread. 60890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) BackgroundThread background; 60990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) background.Start(); 61090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) background.DeleteTarget(target.release()); 61190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 61290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Main thread attempts to dereference the target, violating thread binding. 61390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_DEATH(arrow.target.get(), ""); 61490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 61590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 619