OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/scoped_ptr.h" | 5 #include "base/memory/scoped_ptr.h" |
6 #include "base/memory/weak_ptr.h" | 6 #include "base/memory/weak_ptr.h" |
7 #include "testing/gtest/include/gtest/gtest.h" | 7 #include "testing/gtest/include/gtest/gtest.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/synchronization/waitable_event.h" |
9 #include "base/threading/thread.h" | 10 #include "base/threading/thread.h" |
10 | 11 |
11 namespace base { | 12 namespace base { |
12 namespace { | 13 namespace { |
13 | 14 |
14 template <class T> | 15 template <class T> |
15 class OffThreadObjectCreator { | 16 class OffThreadObjectCreator { |
16 public: | 17 public: |
17 static T* NewObject() { | 18 static T* NewObject() { |
18 T* result; | 19 T* result; |
(...skipping 12 matching lines...) Expand all Loading... |
31 *result = new T; | 32 *result = new T; |
32 } | 33 } |
33 }; | 34 }; |
34 | 35 |
35 struct Base {}; | 36 struct Base {}; |
36 struct Derived : Base {}; | 37 struct Derived : Base {}; |
37 | 38 |
38 struct Producer : SupportsWeakPtr<Producer> {}; | 39 struct Producer : SupportsWeakPtr<Producer> {}; |
39 struct Consumer { WeakPtr<Producer> producer; }; | 40 struct Consumer { WeakPtr<Producer> producer; }; |
40 | 41 |
| 42 // Helper class to create and destroy weak pointer copies |
| 43 // and delete objects on a background thread. |
| 44 class BackgroundThread : public Thread { |
| 45 public: |
| 46 BackgroundThread() |
| 47 : Thread("owner_thread") { |
| 48 } |
| 49 |
| 50 void CreateConsumerFromProducer(Consumer** consumer, Producer* producer) { |
| 51 WaitableEvent completion(true, false); |
| 52 message_loop()->PostTask( |
| 53 FROM_HERE, |
| 54 NewRunnableFunction(&BackgroundThread::DoCreateFromProducer, |
| 55 consumer, |
| 56 producer, |
| 57 &completion)); |
| 58 completion.Wait(); |
| 59 } |
| 60 |
| 61 void CreateConsumerFromConsumer(Consumer** consumer, const Consumer* other) { |
| 62 WaitableEvent completion(true, false); |
| 63 message_loop()->PostTask( |
| 64 FROM_HERE, |
| 65 NewRunnableFunction(&BackgroundThread::DoCreateFromConsumer, |
| 66 consumer, |
| 67 other, |
| 68 &completion)); |
| 69 completion.Wait(); |
| 70 } |
| 71 |
| 72 void DeleteProducer(Producer* object) { |
| 73 WaitableEvent completion(true, false); |
| 74 message_loop()->PostTask( |
| 75 FROM_HERE, |
| 76 NewRunnableFunction(&BackgroundThread::DoDeleteProducer, |
| 77 object, |
| 78 &completion)); |
| 79 completion.Wait(); |
| 80 } |
| 81 |
| 82 void DeleteConsumer(Consumer* object) { |
| 83 WaitableEvent completion(true, false); |
| 84 message_loop()->PostTask( |
| 85 FROM_HERE, |
| 86 NewRunnableFunction(&BackgroundThread::DoDeleteConsumer, |
| 87 object, |
| 88 &completion)); |
| 89 completion.Wait(); |
| 90 } |
| 91 |
| 92 Producer* DeRef(const Consumer* consumer) { |
| 93 WaitableEvent completion(true, false); |
| 94 Producer* result = NULL; |
| 95 message_loop()->PostTask( |
| 96 FROM_HERE, |
| 97 NewRunnableFunction(&BackgroundThread::DoDeRef, |
| 98 consumer, |
| 99 &result, |
| 100 &completion)); |
| 101 completion.Wait(); |
| 102 return result; |
| 103 } |
| 104 |
| 105 protected: |
| 106 static void DoCreateFromConsumer(Consumer** consumer, |
| 107 const Consumer* other, |
| 108 WaitableEvent* completion) { |
| 109 *consumer = new Consumer; |
| 110 **consumer = *other; |
| 111 completion->Signal(); |
| 112 } |
| 113 |
| 114 static void DoCreateFromProducer(Consumer** consumer, |
| 115 Producer* producer, |
| 116 WaitableEvent* completion) { |
| 117 *consumer = new Consumer; |
| 118 (*consumer)->producer = producer->AsWeakPtr(); |
| 119 completion->Signal(); |
| 120 } |
| 121 |
| 122 static void DoDeRef(const Consumer* consumer, |
| 123 Producer** result, |
| 124 WaitableEvent* completion) { |
| 125 *result = consumer->producer.get(); |
| 126 completion->Signal(); |
| 127 } |
| 128 |
| 129 static void DoDeleteProducer(Producer* object, WaitableEvent* completion) { |
| 130 delete object; |
| 131 completion->Signal(); |
| 132 } |
| 133 |
| 134 static void DoDeleteConsumer(Consumer* object, WaitableEvent* completion) { |
| 135 delete object; |
| 136 completion->Signal(); |
| 137 } |
| 138 }; |
| 139 |
41 } // namespace | 140 } // namespace |
42 | 141 |
43 TEST(WeakPtrTest, Basic) { | 142 TEST(WeakPtrTest, Basic) { |
44 int data; | 143 int data; |
45 WeakPtrFactory<int> factory(&data); | 144 WeakPtrFactory<int> factory(&data); |
46 WeakPtr<int> ptr = factory.GetWeakPtr(); | 145 WeakPtr<int> ptr = factory.GetWeakPtr(); |
47 EXPECT_EQ(&data, ptr.get()); | 146 EXPECT_EQ(&data, ptr.get()); |
48 } | 147 } |
49 | 148 |
50 TEST(WeakPtrTest, Comparison) { | 149 TEST(WeakPtrTest, Comparison) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 TEST(WeakPtrTest, SingleThreaded2) { | 240 TEST(WeakPtrTest, SingleThreaded2) { |
142 // Test that it is OK to create a class that has a WeakPtr member on one | 241 // Test that it is OK to create a class that has a WeakPtr member on one |
143 // thread, but use it on another. This tests that we do not trip runtime | 242 // thread, but use it on another. This tests that we do not trip runtime |
144 // checks that ensure that a weak reference is not used by multiple threads. | 243 // checks that ensure that a weak reference is not used by multiple threads. |
145 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject()); | 244 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject()); |
146 Producer producer; | 245 Producer producer; |
147 consumer->producer = producer.AsWeakPtr(); | 246 consumer->producer = producer.AsWeakPtr(); |
148 EXPECT_EQ(&producer, consumer->producer.get()); | 247 EXPECT_EQ(&producer, consumer->producer.get()); |
149 } | 248 } |
150 | 249 |
| 250 TEST(WeakPtrTest, MoveOwnershipImplicit) { |
| 251 // Move object ownership to other thread by releasing all weak pointers |
| 252 // on the original thread first. Establishing weak pointers on a different |
| 253 // thread after previous pointers have been destroyed implicitly reattaches |
| 254 // the thread checks. |
| 255 // - Thread A creates object and weak pointer |
| 256 // - Thread A deletes the weak pointer |
| 257 // - Thread B creates weak pointer |
| 258 // - Thread B derefs weak pointer |
| 259 // - Thread B deletes object |
| 260 BackgroundThread thread; |
| 261 thread.Start(); |
| 262 Producer* producer = new Producer(); |
| 263 { |
| 264 WeakPtr<Producer> weak_ptr = producer->AsWeakPtr(); |
| 265 } |
| 266 Consumer* consumer; |
| 267 thread.CreateConsumerFromProducer(&consumer, producer); |
| 268 EXPECT_EQ(thread.DeRef(consumer), producer); |
| 269 thread.DeleteProducer(producer); |
| 270 thread.DeleteConsumer(consumer); |
| 271 } |
| 272 |
| 273 TEST(WeakPtrTest, MoveOwnershipExplicit) { |
| 274 // Test that we do not trip any checks if we establish weak references |
| 275 // on one thread and delete the object on another thread after explicit |
| 276 // detachment. |
| 277 // - Thread A creates object |
| 278 // - Thread B creates weak pointer |
| 279 // - Thread B releases weak pointer |
| 280 // - Detach owner from Thread B |
| 281 // - Thread A destroys object |
| 282 BackgroundThread thread; |
| 283 thread.Start(); |
| 284 Producer producer; |
| 285 Consumer* consumer; |
| 286 thread.CreateConsumerFromProducer(&consumer, &producer); |
| 287 EXPECT_EQ(thread.DeRef(consumer), &producer); |
| 288 thread.DeleteConsumer(consumer); |
| 289 producer.DetachFromThread(); |
| 290 } |
| 291 |
| 292 TEST(WeakPtrTest, ThreadARefOutlivesThreadBRef) { |
| 293 // Originating thread has a WeakPtr that outlives others. |
| 294 // - Thread A creates WeakPtr<> and passes copy to Thread B |
| 295 // - Destruct the pointer on Thread B |
| 296 // - Destruct the pointer on Thread A |
| 297 BackgroundThread thread; |
| 298 thread.Start(); |
| 299 Producer producer; |
| 300 Consumer consumer; |
| 301 consumer.producer = producer.AsWeakPtr(); |
| 302 Consumer* consumer_copy; |
| 303 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); |
| 304 EXPECT_EQ(consumer_copy->producer, &producer); |
| 305 thread.DeleteConsumer(consumer_copy); |
| 306 } |
| 307 |
| 308 TEST(WeakPtrTest, ThreadBRefOutlivesThreadARef) { |
| 309 // Originating thread drops all references before another thread. |
| 310 // - Thread A creates WeakPtr<> and passes copy to Thread B |
| 311 // - Destruct the pointer on Thread A |
| 312 // - Destruct the pointer on Thread B |
| 313 BackgroundThread thread; |
| 314 thread.Start(); |
| 315 Producer producer; |
| 316 Consumer* consumer_copy; |
| 317 { |
| 318 Consumer consumer; |
| 319 consumer.producer = producer.AsWeakPtr(); |
| 320 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); |
| 321 } |
| 322 EXPECT_EQ(consumer_copy->producer, &producer); |
| 323 thread.DeleteConsumer(consumer_copy); |
| 324 } |
| 325 |
| 326 TEST(WeakPtrTest, OwnerThreadDeletesObject) { |
| 327 // Originating thread invalidates WeakPtrs while its held by other thread. |
| 328 // - Thread A creates WeakPtr<> and passes Copy to Thread B |
| 329 // - WeakReferenceOwner gets destroyed on Thread A |
| 330 // - WeakPtr gets destroyed on Thread B |
| 331 BackgroundThread thread; |
| 332 thread.Start(); |
| 333 Consumer* consumer_copy; |
| 334 { |
| 335 Producer producer; |
| 336 Consumer consumer; |
| 337 consumer.producer = producer.AsWeakPtr(); |
| 338 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); |
| 339 } |
| 340 EXPECT_TRUE(consumer_copy->producer == NULL); |
| 341 thread.DeleteConsumer(consumer_copy); |
| 342 } |
| 343 |
151 } // namespace base | 344 } // namespace base |
OLD | NEW |