| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/weak_ptr.h" | 5 #include "base/memory/weak_ptr.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 } | 30 } |
| 31 DCHECK(result); // We synchronized on thread destruction above. | 31 DCHECK(result); // We synchronized on thread destruction above. |
| 32 return result; | 32 return result; |
| 33 } | 33 } |
| 34 private: | 34 private: |
| 35 static void CreateObject(T** result) { | 35 static void CreateObject(T** result) { |
| 36 *result = new T; | 36 *result = new T; |
| 37 } | 37 } |
| 38 }; | 38 }; |
| 39 | 39 |
| 40 struct Base { std::string member; }; | 40 struct Base { |
| 41 std::string member; |
| 42 }; |
| 41 struct Derived : Base {}; | 43 struct Derived : Base {}; |
| 42 | 44 |
| 43 struct Producer : SupportsWeakPtr<Producer> {}; | 45 struct Target : SupportsWeakPtr<Target> {}; |
| 44 struct DerivedProducer : Producer {}; | 46 struct DerivedTarget : Target {}; |
| 45 struct Consumer { WeakPtr<Producer> producer; }; | 47 struct Arrow { |
| 48 WeakPtr<Target> target; |
| 49 }; |
| 46 | 50 |
| 47 // Helper class to create and destroy weak pointer copies | 51 // Helper class to create and destroy weak pointer copies |
| 48 // and delete objects on a background thread. | 52 // and delete objects on a background thread. |
| 49 class BackgroundThread : public Thread { | 53 class BackgroundThread : public Thread { |
| 50 public: | 54 public: |
| 51 BackgroundThread() : Thread("owner_thread") {} | 55 BackgroundThread() : Thread("owner_thread") {} |
| 52 | 56 |
| 53 virtual ~BackgroundThread() { | 57 virtual ~BackgroundThread() { |
| 54 Stop(); | 58 Stop(); |
| 55 } | 59 } |
| 56 | 60 |
| 57 void CreateConsumerFromProducer(Consumer** consumer, Producer* producer) { | 61 void CreateArrowFromTarget(Arrow** arrow, Target* target) { |
| 58 WaitableEvent completion(true, false); | 62 WaitableEvent completion(true, false); |
| 59 message_loop()->PostTask( | 63 message_loop()->PostTask( |
| 60 FROM_HERE, | 64 FROM_HERE, |
| 61 base::Bind(&BackgroundThread::DoCreateFromProducer, consumer, producer, | 65 base::Bind(&BackgroundThread::DoCreateArrowFromTarget, |
| 62 &completion)); | 66 arrow, target, &completion)); |
| 63 completion.Wait(); | 67 completion.Wait(); |
| 64 } | 68 } |
| 65 | 69 |
| 66 void CreateConsumerFromConsumer(Consumer** consumer, const Consumer* other) { | 70 void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) { |
| 67 WaitableEvent completion(true, false); | 71 WaitableEvent completion(true, false); |
| 68 message_loop()->PostTask( | 72 message_loop()->PostTask( |
| 69 FROM_HERE, | 73 FROM_HERE, |
| 70 base::Bind(&BackgroundThread::DoCreateFromConsumer, consumer, other, | 74 base::Bind(&BackgroundThread::DoCreateArrowFromArrow, |
| 71 &completion)); | 75 arrow, other, &completion)); |
| 72 completion.Wait(); | 76 completion.Wait(); |
| 73 } | 77 } |
| 74 | 78 |
| 75 void DeleteProducer(Producer* object) { | 79 void DeleteTarget(Target* object) { |
| 76 WaitableEvent completion(true, false); | 80 WaitableEvent completion(true, false); |
| 77 message_loop()->PostTask( | 81 message_loop()->PostTask( |
| 78 FROM_HERE, | 82 FROM_HERE, |
| 79 base::Bind(&BackgroundThread::DoDeleteProducer, object, &completion)); | 83 base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion)); |
| 80 completion.Wait(); | 84 completion.Wait(); |
| 81 } | 85 } |
| 82 | 86 |
| 83 void DeleteConsumer(Consumer* object) { | 87 void DeleteArrow(Arrow* object) { |
| 84 WaitableEvent completion(true, false); | 88 WaitableEvent completion(true, false); |
| 85 message_loop()->PostTask( | 89 message_loop()->PostTask( |
| 86 FROM_HERE, | 90 FROM_HERE, |
| 87 base::Bind(&BackgroundThread::DoDeleteConsumer, object, &completion)); | 91 base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion)); |
| 88 completion.Wait(); | 92 completion.Wait(); |
| 89 } | 93 } |
| 90 | 94 |
| 91 Producer* DeRef(const Consumer* consumer) { | 95 Target* DeRef(const Arrow* arrow) { |
| 92 WaitableEvent completion(true, false); | 96 WaitableEvent completion(true, false); |
| 93 Producer* result = NULL; | 97 Target* result = NULL; |
| 94 message_loop()->PostTask( | 98 message_loop()->PostTask( |
| 95 FROM_HERE, | 99 FROM_HERE, |
| 96 base::Bind(&BackgroundThread::DoDeRef, consumer, &result, &completion)); | 100 base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion)); |
| 97 completion.Wait(); | 101 completion.Wait(); |
| 98 return result; | 102 return result; |
| 99 } | 103 } |
| 100 | 104 |
| 101 protected: | 105 protected: |
| 102 static void DoCreateFromConsumer(Consumer** consumer, | 106 static void DoCreateArrowFromArrow(Arrow** arrow, |
| 103 const Consumer* other, | 107 const Arrow* other, |
| 104 WaitableEvent* completion) { | 108 WaitableEvent* completion) { |
| 105 *consumer = new Consumer; | 109 *arrow = new Arrow; |
| 106 **consumer = *other; | 110 **arrow = *other; |
| 107 completion->Signal(); | 111 completion->Signal(); |
| 108 } | 112 } |
| 109 | 113 |
| 110 static void DoCreateFromProducer(Consumer** consumer, | 114 static void DoCreateArrowFromTarget(Arrow** arrow, |
| 111 Producer* producer, | 115 Target* target, |
| 112 WaitableEvent* completion) { | 116 WaitableEvent* completion) { |
| 113 *consumer = new Consumer; | 117 *arrow = new Arrow; |
| 114 (*consumer)->producer = producer->AsWeakPtr(); | 118 (*arrow)->target = target->AsWeakPtr(); |
| 115 completion->Signal(); | 119 completion->Signal(); |
| 116 } | 120 } |
| 117 | 121 |
| 118 static void DoDeRef(const Consumer* consumer, | 122 static void DoDeRef(const Arrow* arrow, |
| 119 Producer** result, | 123 Target** result, |
| 120 WaitableEvent* completion) { | 124 WaitableEvent* completion) { |
| 121 *result = consumer->producer.get(); | 125 *result = arrow->target.get(); |
| 122 completion->Signal(); | 126 completion->Signal(); |
| 123 } | 127 } |
| 124 | 128 |
| 125 static void DoDeleteProducer(Producer* object, WaitableEvent* completion) { | 129 static void DoDeleteTarget(Target* object, WaitableEvent* completion) { |
| 126 delete object; | 130 delete object; |
| 127 completion->Signal(); | 131 completion->Signal(); |
| 128 } | 132 } |
| 129 | 133 |
| 130 static void DoDeleteConsumer(Consumer* object, WaitableEvent* completion) { | 134 static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) { |
| 131 delete object; | 135 delete object; |
| 132 completion->Signal(); | 136 completion->Signal(); |
| 133 } | 137 } |
| 134 }; | 138 }; |
| 135 | 139 |
| 136 } // namespace | 140 } // namespace |
| 137 | 141 |
| 138 TEST(WeakPtrTest, Basic) { | 142 TEST(WeakPtrFactoryTest, Basic) { |
| 139 int data; | 143 int data; |
| 140 WeakPtrFactory<int> factory(&data); | 144 WeakPtrFactory<int> factory(&data); |
| 141 WeakPtr<int> ptr = factory.GetWeakPtr(); | 145 WeakPtr<int> ptr = factory.GetWeakPtr(); |
| 142 EXPECT_EQ(&data, ptr.get()); | 146 EXPECT_EQ(&data, ptr.get()); |
| 143 } | 147 } |
| 144 | 148 |
| 145 TEST(WeakPtrTest, Comparison) { | 149 TEST(WeakPtrFactoryTest, Comparison) { |
| 146 int data; | 150 int data; |
| 147 WeakPtrFactory<int> factory(&data); | 151 WeakPtrFactory<int> factory(&data); |
| 148 WeakPtr<int> ptr = factory.GetWeakPtr(); | 152 WeakPtr<int> ptr = factory.GetWeakPtr(); |
| 149 WeakPtr<int> ptr2 = ptr; | 153 WeakPtr<int> ptr2 = ptr; |
| 150 EXPECT_TRUE(ptr == ptr2); | 154 EXPECT_EQ(ptr, ptr2); |
| 151 } | 155 } |
| 152 | 156 |
| 153 TEST(WeakPtrTest, OutOfScope) { | 157 TEST(WeakPtrFactoryTest, OutOfScope) { |
| 154 WeakPtr<int> ptr; | 158 WeakPtr<int> ptr; |
| 155 EXPECT_TRUE(ptr.get() == NULL); | 159 EXPECT_EQ(NULL, ptr.get()); |
| 156 { | 160 { |
| 157 int data; | 161 int data; |
| 158 WeakPtrFactory<int> factory(&data); | 162 WeakPtrFactory<int> factory(&data); |
| 159 ptr = factory.GetWeakPtr(); | 163 ptr = factory.GetWeakPtr(); |
| 160 } | 164 } |
| 161 EXPECT_TRUE(ptr.get() == NULL); | 165 EXPECT_EQ(NULL, ptr.get()); |
| 162 } | 166 } |
| 163 | 167 |
| 164 TEST(WeakPtrTest, Multiple) { | 168 TEST(WeakPtrFactoryTest, Multiple) { |
| 165 WeakPtr<int> a, b; | 169 WeakPtr<int> a, b; |
| 166 { | 170 { |
| 167 int data; | 171 int data; |
| 168 WeakPtrFactory<int> factory(&data); | 172 WeakPtrFactory<int> factory(&data); |
| 169 a = factory.GetWeakPtr(); | 173 a = factory.GetWeakPtr(); |
| 170 b = factory.GetWeakPtr(); | 174 b = factory.GetWeakPtr(); |
| 171 EXPECT_EQ(&data, a.get()); | 175 EXPECT_EQ(&data, a.get()); |
| 172 EXPECT_EQ(&data, b.get()); | 176 EXPECT_EQ(&data, b.get()); |
| 173 } | 177 } |
| 174 EXPECT_TRUE(a.get() == NULL); | 178 EXPECT_EQ(NULL, a.get()); |
| 175 EXPECT_TRUE(b.get() == NULL); | 179 EXPECT_EQ(NULL, b.get()); |
| 176 } | 180 } |
| 177 | 181 |
| 178 TEST(WeakPtrTest, MultipleStaged) { | 182 TEST(WeakPtrFactoryTest, MultipleStaged) { |
| 179 WeakPtr<int> a; | 183 WeakPtr<int> a; |
| 180 { | 184 { |
| 181 int data; | 185 int data; |
| 182 WeakPtrFactory<int> factory(&data); | 186 WeakPtrFactory<int> factory(&data); |
| 183 a = factory.GetWeakPtr(); | 187 a = factory.GetWeakPtr(); |
| 184 { | 188 { |
| 185 WeakPtr<int> b = factory.GetWeakPtr(); | 189 WeakPtr<int> b = factory.GetWeakPtr(); |
| 186 } | 190 } |
| 187 EXPECT_TRUE(a.get() != NULL); | 191 EXPECT_TRUE(NULL != a.get()); |
| 188 } | 192 } |
| 189 EXPECT_TRUE(a.get() == NULL); | 193 EXPECT_EQ(NULL, a.get()); |
| 190 } | 194 } |
| 191 | 195 |
| 192 TEST(WeakPtrTest, UpCast) { | 196 TEST(WeakPtrFactoryTest, Dereference) { |
| 197 Base data; |
| 198 data.member = "123456"; |
| 199 WeakPtrFactory<Base> factory(&data); |
| 200 WeakPtr<Base> ptr = factory.GetWeakPtr(); |
| 201 EXPECT_EQ(&data, ptr.get()); |
| 202 EXPECT_EQ(data.member, (*ptr).member); |
| 203 EXPECT_EQ(data.member, ptr->member); |
| 204 } |
| 205 |
| 206 TEST(WeakPtrFactoryTest, UpCast) { |
| 193 Derived data; | 207 Derived data; |
| 194 WeakPtrFactory<Derived> factory(&data); | 208 WeakPtrFactory<Derived> factory(&data); |
| 195 WeakPtr<Base> ptr = factory.GetWeakPtr(); | 209 WeakPtr<Base> ptr = factory.GetWeakPtr(); |
| 196 ptr = factory.GetWeakPtr(); | 210 ptr = factory.GetWeakPtr(); |
| 197 EXPECT_EQ(ptr.get(), &data); | 211 EXPECT_EQ(ptr.get(), &data); |
| 198 } | 212 } |
| 199 | 213 |
| 200 TEST(WeakPtrTest, SupportsWeakPtr) { | 214 TEST(WeakPtrTest, SupportsWeakPtr) { |
| 201 Producer f; | 215 Target target; |
| 202 WeakPtr<Producer> ptr = f.AsWeakPtr(); | 216 WeakPtr<Target> ptr = target.AsWeakPtr(); |
| 203 EXPECT_EQ(&f, ptr.get()); | 217 EXPECT_EQ(&target, ptr.get()); |
| 204 } | 218 } |
| 205 | 219 |
| 206 TEST(WeakPtrTest, DerivedProducer) { | 220 TEST(WeakPtrTest, DerivedTarget) { |
| 207 DerivedProducer f; | 221 DerivedTarget target; |
| 208 WeakPtr<DerivedProducer> ptr = AsWeakPtr(&f); | 222 WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target); |
| 209 EXPECT_EQ(&f, ptr.get()); | 223 EXPECT_EQ(&target, ptr.get()); |
| 210 } | 224 } |
| 211 | 225 |
| 212 TEST(WeakPtrTest, InvalidateWeakPtrs) { | 226 TEST(WeakPtrTest, InvalidateWeakPtrs) { |
| 213 int data; | 227 int data; |
| 214 WeakPtrFactory<int> factory(&data); | 228 WeakPtrFactory<int> factory(&data); |
| 215 WeakPtr<int> ptr = factory.GetWeakPtr(); | 229 WeakPtr<int> ptr = factory.GetWeakPtr(); |
| 216 EXPECT_EQ(&data, ptr.get()); | 230 EXPECT_EQ(&data, ptr.get()); |
| 217 EXPECT_TRUE(factory.HasWeakPtrs()); | 231 EXPECT_TRUE(factory.HasWeakPtrs()); |
| 218 factory.InvalidateWeakPtrs(); | 232 factory.InvalidateWeakPtrs(); |
| 219 EXPECT_TRUE(ptr.get() == NULL); | 233 EXPECT_EQ(NULL, ptr.get()); |
| 220 EXPECT_FALSE(factory.HasWeakPtrs()); | 234 EXPECT_FALSE(factory.HasWeakPtrs()); |
| 221 } | 235 } |
| 222 | 236 |
| 223 TEST(WeakPtrTest, HasWeakPtrs) { | 237 TEST(WeakPtrTest, HasWeakPtrs) { |
| 224 int data; | 238 int data; |
| 225 WeakPtrFactory<int> factory(&data); | 239 WeakPtrFactory<int> factory(&data); |
| 226 { | 240 { |
| 227 WeakPtr<int> ptr = factory.GetWeakPtr(); | 241 WeakPtr<int> ptr = factory.GetWeakPtr(); |
| 228 EXPECT_TRUE(factory.HasWeakPtrs()); | 242 EXPECT_TRUE(factory.HasWeakPtrs()); |
| 229 } | 243 } |
| 230 EXPECT_FALSE(factory.HasWeakPtrs()); | 244 EXPECT_FALSE(factory.HasWeakPtrs()); |
| 231 } | 245 } |
| 232 | 246 |
| 233 TEST(WeakPtrTest, SingleThreaded1) { | 247 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) { |
| 234 // Test that it is OK to create a class that supports weak references on one | 248 // Test that it is OK to create an object that supports WeakPtr on one thread, |
| 249 // but use it on another. This tests that we do not trip runtime checks that |
| 250 // ensure that a WeakPtr is not used by multiple threads. |
| 251 scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject()); |
| 252 WeakPtr<Target> weak_ptr = target->AsWeakPtr(); |
| 253 EXPECT_EQ(target.get(), weak_ptr.get()); |
| 254 } |
| 255 |
| 256 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) { |
| 257 // Test that it is OK to create an object that has a WeakPtr member on one |
| 235 // thread, but use it on another. This tests that we do not trip runtime | 258 // thread, but use it on another. This tests that we do not trip runtime |
| 236 // checks that ensure that a weak reference is not used by multiple threads. | 259 // checks that ensure that a WeakPtr is not used by multiple threads. |
| 237 scoped_ptr<Producer> producer(OffThreadObjectCreator<Producer>::NewObject()); | 260 scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject()); |
| 238 WeakPtr<Producer> weak_producer = producer->AsWeakPtr(); | 261 Target target; |
| 239 EXPECT_EQ(producer.get(), weak_producer.get()); | 262 arrow->target = target.AsWeakPtr(); |
| 240 } | 263 EXPECT_EQ(&target, arrow->target.get()); |
| 241 | 264 } |
| 242 TEST(WeakPtrTest, SingleThreaded2) { | 265 |
| 243 // Test that it is OK to create a class that has a WeakPtr member on one | 266 TEST(WeakPtrTest, MoveOwnershipImplicitly) { |
| 244 // thread, but use it on another. This tests that we do not trip runtime | 267 // Move object ownership to another thread by releasing all weak pointers |
| 245 // checks that ensure that a weak reference is not used by multiple threads. | 268 // on the original thread first, and then establish WeakPtr on a different |
| 246 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject()); | 269 // thread. |
| 247 Producer producer; | 270 BackgroundThread background; |
| 248 consumer->producer = producer.AsWeakPtr(); | 271 background.Start(); |
| 249 EXPECT_EQ(&producer, consumer->producer.get()); | 272 |
| 250 } | 273 Target* target = new Target(); |
| 251 | 274 { |
| 252 TEST(WeakPtrTest, MoveOwnershipImplicit) { | 275 WeakPtr<Target> weak_ptr = target->AsWeakPtr(); |
| 253 // Move object ownership to other thread by releasing all weak pointers | 276 // Main thread deletes the WeakPtr, then the thread ownership of the |
| 254 // on the original thread first. Establishing weak pointers on a different | 277 // object can be implicitly moved. |
| 255 // thread after previous pointers have been destroyed implicitly reattaches | 278 } |
| 256 // the thread checks. | 279 Arrow* arrow; |
| 257 // - Thread A creates object and weak pointer | 280 |
| 258 // - Thread A deletes the weak pointer | 281 // Background thread creates WeakPtr(and implicitly owns the object). |
| 259 // - Thread B creates weak pointer | 282 background.CreateArrowFromTarget(&arrow, target); |
| 260 // - Thread B derefs weak pointer | 283 EXPECT_EQ(background.DeRef(arrow), target); |
| 261 // - Thread B deletes object | 284 |
| 262 BackgroundThread thread; | 285 { |
| 263 thread.Start(); | 286 // Main thread creates another WeakPtr, but this does not trigger implicitly |
| 264 Producer* producer = new Producer(); | 287 // thread ownership move. |
| 265 { | 288 Arrow arrow; |
| 266 WeakPtr<Producer> weak_ptr = producer->AsWeakPtr(); | 289 arrow.target = target->AsWeakPtr(); |
| 267 } | 290 |
| 268 Consumer* consumer; | 291 // The new WeakPtr is owned by background thread. |
| 269 thread.CreateConsumerFromProducer(&consumer, producer); | 292 EXPECT_EQ(target, background.DeRef(&arrow)); |
| 270 EXPECT_EQ(thread.DeRef(consumer), producer); | 293 } |
| 271 thread.DeleteProducer(producer); | 294 |
| 272 thread.DeleteConsumer(consumer); | 295 // Target can only be deleted on background thread. |
| 273 } | 296 background.DeleteTarget(target); |
| 274 | 297 background.DeleteArrow(arrow); |
| 275 TEST(WeakPtrTest, MoveOwnershipExplicit) { | 298 } |
| 276 // Test that we do not trip any checks if we establish weak references | 299 |
| 277 // on one thread and delete the object on another thread after explicit | 300 TEST(WeakPtrTest, MoveOwnershipExplicitlyObjectNotReferenced) { |
| 278 // detachment. | 301 // Case 1: The target is not bound to any thread yet. So calling |
| 279 // - Thread A creates object | 302 // DetachFromThread() is a no-op. |
| 280 // - Thread B creates weak pointer | 303 Target target; |
| 281 // - Thread B releases weak pointer | 304 target.DetachFromThread(); |
| 282 // - Detach owner from Thread B | 305 |
| 283 // - Thread A destroys object | 306 // Case 2: The target is bound to main thread but no WeakPtr is pointing to |
| 284 BackgroundThread thread; | 307 // it. In this case, it will be re-bound to any thread trying to get a |
| 285 thread.Start(); | 308 // WeakPtr pointing to it. So detach function call is again no-op. |
| 286 Producer producer; | 309 { |
| 287 Consumer* consumer; | 310 WeakPtr<Target> weak_ptr = target.AsWeakPtr(); |
| 288 thread.CreateConsumerFromProducer(&consumer, &producer); | 311 } |
| 289 EXPECT_EQ(thread.DeRef(consumer), &producer); | 312 target.DetachFromThread(); |
| 290 thread.DeleteConsumer(consumer); | 313 } |
| 291 producer.DetachFromThread(); | 314 |
| 292 } | 315 TEST(WeakPtrTest, MoveOwnershipExplicitly) { |
| 293 | 316 BackgroundThread background; |
| 294 TEST(WeakPtrTest, ThreadARefOutlivesThreadBRef) { | 317 background.Start(); |
| 318 |
| 319 Arrow* arrow; |
| 320 { |
| 321 Target target; |
| 322 // Background thread creates WeakPtr(and implicitly owns the object). |
| 323 background.CreateArrowFromTarget(&arrow, &target); |
| 324 EXPECT_EQ(&target, background.DeRef(arrow)); |
| 325 |
| 326 // Detach from background thread. |
| 327 target.DetachFromThread(); |
| 328 |
| 329 // Re-bind to main thread. |
| 330 EXPECT_EQ(&target, arrow->target.get()); |
| 331 |
| 332 // Main thread can now delete the target. |
| 333 } |
| 334 |
| 335 // WeakPtr can be deleted on non-owner thread. |
| 336 background.DeleteArrow(arrow); |
| 337 } |
| 338 |
| 339 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) { |
| 295 // Originating thread has a WeakPtr that outlives others. | 340 // Originating thread has a WeakPtr that outlives others. |
| 296 // - Thread A creates WeakPtr<> and passes copy to Thread B | 341 // - Main thread creates a WeakPtr |
| 297 // - Destruct the pointer on Thread B | 342 // - Background thread creates a WeakPtr copy from the one in main thread |
| 298 // - Destruct the pointer on Thread A | 343 // - Destruct the WeakPtr on background thread |
| 299 BackgroundThread thread; | 344 // - Destruct the WeakPtr on main thread |
| 300 thread.Start(); | 345 BackgroundThread background; |
| 301 Producer producer; | 346 background.Start(); |
| 302 Consumer consumer; | 347 |
| 303 consumer.producer = producer.AsWeakPtr(); | 348 Target target; |
| 304 Consumer* consumer_copy; | 349 Arrow arrow; |
| 305 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); | 350 arrow.target = target.AsWeakPtr(); |
| 306 EXPECT_EQ(consumer_copy->producer, &producer); | 351 |
| 307 thread.DeleteConsumer(consumer_copy); | 352 Arrow* arrow_copy; |
| 308 } | 353 background.CreateArrowFromArrow(&arrow_copy, &arrow); |
| 309 | 354 EXPECT_EQ(arrow_copy->target, &target); |
| 310 TEST(WeakPtrTest, ThreadBRefOutlivesThreadARef) { | 355 background.DeleteArrow(arrow_copy); |
| 356 } |
| 357 |
| 358 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) { |
| 311 // Originating thread drops all references before another thread. | 359 // Originating thread drops all references before another thread. |
| 312 // - Thread A creates WeakPtr<> and passes copy to Thread B | 360 // - Main thread creates a WeakPtr and passes copy to background thread |
| 313 // - Destruct the pointer on Thread A | 361 // - Destruct the pointer on main thread |
| 314 // - Destruct the pointer on Thread B | 362 // - Destruct the pointer on background thread |
| 315 BackgroundThread thread; | 363 BackgroundThread background; |
| 316 thread.Start(); | 364 background.Start(); |
| 317 Producer producer; | 365 |
| 318 Consumer* consumer_copy; | 366 Target target; |
| 319 { | 367 Arrow* arrow_copy; |
| 320 Consumer consumer; | 368 { |
| 321 consumer.producer = producer.AsWeakPtr(); | 369 Arrow arrow; |
| 322 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); | 370 arrow.target = target.AsWeakPtr(); |
| 323 } | 371 background.CreateArrowFromArrow(&arrow_copy, &arrow); |
| 324 EXPECT_EQ(consumer_copy->producer, &producer); | 372 } |
| 325 thread.DeleteConsumer(consumer_copy); | 373 EXPECT_EQ(arrow_copy->target, &target); |
| 374 background.DeleteArrow(arrow_copy); |
| 326 } | 375 } |
| 327 | 376 |
| 328 TEST(WeakPtrTest, OwnerThreadDeletesObject) { | 377 TEST(WeakPtrTest, OwnerThreadDeletesObject) { |
| 329 // Originating thread invalidates WeakPtrs while its held by other thread. | 378 // Originating thread invalidates WeakPtrs while its held by other thread. |
| 330 // - Thread A creates WeakPtr<> and passes Copy to Thread B | 379 // - Main thread creates WeakPtr and passes Copy to background thread |
| 331 // - WeakReferenceOwner gets destroyed on Thread A | 380 // - Object gets destroyed on main thread |
| 381 // (invalidates WeakPtr on background thread) |
| 332 // - WeakPtr gets destroyed on Thread B | 382 // - WeakPtr gets destroyed on Thread B |
| 333 BackgroundThread thread; | 383 BackgroundThread background; |
| 334 thread.Start(); | 384 background.Start(); |
| 335 Consumer* consumer_copy; | 385 Arrow* arrow_copy; |
| 336 { | 386 { |
| 337 Producer producer; | 387 Target target; |
| 338 Consumer consumer; | 388 Arrow arrow; |
| 339 consumer.producer = producer.AsWeakPtr(); | 389 arrow.target = target.AsWeakPtr(); |
| 340 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); | 390 background.CreateArrowFromArrow(&arrow_copy, &arrow); |
| 341 } | 391 } |
| 342 EXPECT_TRUE(consumer_copy->producer == NULL); | 392 EXPECT_EQ(NULL, arrow_copy->target.get()); |
| 343 thread.DeleteConsumer(consumer_copy); | 393 background.DeleteArrow(arrow_copy); |
| 344 } | 394 } |
| 345 | 395 |
| 346 TEST(WeakPtrTest, Dereference) { | 396 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) { |
| 347 Base data; | 397 // Main thread creates a Target object. |
| 348 data.member = "123456"; | 398 Target target; |
| 349 WeakPtrFactory<Base> factory(&data); | 399 // Main thread creates an arrow referencing the Target. |
| 350 WeakPtr<Base> ptr = factory.GetWeakPtr(); | 400 Arrow* arrow = new Arrow(); |
| 351 EXPECT_EQ(&data, ptr.get()); | 401 arrow->target = target.AsWeakPtr(); |
| 352 EXPECT_EQ(data.member, (*ptr).member); | 402 |
| 353 EXPECT_EQ(data.member, ptr->member); | 403 // Background can delete arrow (as well as the WeakPtr inside). |
| 354 } | 404 BackgroundThread background; |
| 405 background.Start(); |
| 406 background.DeleteArrow(arrow); |
| 407 } |
| 408 |
| 409 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST |
| 410 |
| 411 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) { |
| 412 // The default style "fast" does not support multi-threaded tests |
| 413 // (introduces deadlock on Linux). |
| 414 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 415 |
| 416 BackgroundThread background; |
| 417 background.Start(); |
| 418 |
| 419 // Main thread creates a Target object. |
| 420 Target target; |
| 421 // Main thread creates an arrow referencing the Target. |
| 422 Arrow arrow; |
| 423 arrow.target = target.AsWeakPtr(); |
| 424 |
| 425 // Background copies the WeakPtr. |
| 426 Arrow* arrow_copy; |
| 427 background.CreateArrowFromArrow(&arrow_copy, &arrow); |
| 428 |
| 429 // The copy is still bound to main thread so I can deref. |
| 430 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get()); |
| 431 |
| 432 // Although background thread created the copy, it can not deref the copied |
| 433 // WeakPtr. |
| 434 ASSERT_DEATH(background.DeRef(arrow_copy), ""); |
| 435 |
| 436 background.DeleteArrow(arrow_copy); |
| 437 } |
| 438 |
| 439 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtr) { |
| 440 // The default style "fast" does not support multi-threaded tests |
| 441 // (introduces deadlock on Linux). |
| 442 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 443 |
| 444 // Main thread creates a Target object. |
| 445 Target target; |
| 446 |
| 447 // Main thread creates an arrow referencing the Target (so target's |
| 448 // thread ownership can not be implicitly moved). |
| 449 Arrow arrow; |
| 450 arrow.target = target.AsWeakPtr(); |
| 451 |
| 452 // Background thread tries to deref target, which violates thread ownership. |
| 453 BackgroundThread background; |
| 454 background.Start(); |
| 455 ASSERT_DEATH(background.DeRef(&arrow), ""); |
| 456 } |
| 457 |
| 458 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObject) { |
| 459 // The default style "fast" does not support multi-threaded tests |
| 460 // (introduces deadlock on Linux). |
| 461 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; |
| 462 |
| 463 scoped_ptr<Target> target(new Target()); |
| 464 // Main thread creates an arrow referencing the Target (so target's thread |
| 465 // ownership can not be implicitly moved). |
| 466 Arrow arrow; |
| 467 arrow.target = target->AsWeakPtr(); |
| 468 |
| 469 // Background thread tries to delete target, which violates thread ownership. |
| 470 BackgroundThread background; |
| 471 background.Start(); |
| 472 ASSERT_DEATH(background.DeleteTarget(target.release()), ""); |
| 473 } |
| 474 |
| 475 #endif |
| 355 | 476 |
| 356 } // namespace base | 477 } // namespace base |
| OLD | NEW |