Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: base/memory/weak_ptr_unittest.cc

Issue 10690080: Rename/re-comment tests and added new death tests for WeakPtr (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/memory/weak_ptr.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
OLDNEW
« no previous file with comments | « base/memory/weak_ptr.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698