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

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
« base/memory/weak_ptr.h ('K') | « 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 22 matching lines...) Expand all
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 { std::string member; };
41 struct Derived : Base {}; 41 struct Derived : Base {};
42 42
43 struct Producer : SupportsWeakPtr<Producer> {}; 43 struct Target : SupportsWeakPtr<Target> {};
44 struct DerivedProducer : Producer {}; 44 struct DerivedTarget : Target {};
45 struct Consumer { WeakPtr<Producer> producer; }; 45 struct Arrow { WeakPtr<Target> target; };
Ryan Sleevi 2012/07/10 00:06:44 style nit: struct Arrow { WeakPtr<Target> targe
kaiwang 2012/07/10 22:21:19 Done.
46 46
47 // Helper class to create and destroy weak pointer copies 47 // Helper class to create and destroy weak pointer copies
48 // and delete objects on a background thread. 48 // and delete objects on a background thread.
49 class BackgroundThread : public Thread { 49 class BackgroundThread : public Thread {
50 public: 50 public:
51 BackgroundThread() : Thread("owner_thread") {} 51 BackgroundThread() : Thread("owner_thread") {}
52 52
53 virtual ~BackgroundThread() { 53 virtual ~BackgroundThread() {
54 Stop(); 54 Stop();
55 } 55 }
56 56
57 void CreateConsumerFromProducer(Consumer** consumer, Producer* producer) { 57 void CreateArrowFromTarget(Arrow** arrow, Target* target) {
58 WaitableEvent completion(true, false); 58 WaitableEvent completion(true, false);
59 message_loop()->PostTask( 59 message_loop()->PostTask(
60 FROM_HERE, 60 FROM_HERE,
61 base::Bind(&BackgroundThread::DoCreateFromProducer, consumer, producer, 61 base::Bind(&BackgroundThread::DoCreateFromTarget, arrow, target,
62 &completion)); 62 &completion));
63 completion.Wait(); 63 completion.Wait();
64 } 64 }
65 65
66 void CreateConsumerFromConsumer(Consumer** consumer, const Consumer* other) { 66 void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
67 WaitableEvent completion(true, false); 67 WaitableEvent completion(true, false);
68 message_loop()->PostTask( 68 message_loop()->PostTask(
69 FROM_HERE, 69 FROM_HERE,
70 base::Bind(&BackgroundThread::DoCreateFromConsumer, consumer, other, 70 base::Bind(&BackgroundThread::DoCreateFromArrow, arrow, other,
71 &completion)); 71 &completion));
72 completion.Wait(); 72 completion.Wait();
73 } 73 }
74 74
75 void DeleteProducer(Producer* object) { 75 void DeleteTarget(Target* object) {
76 WaitableEvent completion(true, false); 76 WaitableEvent completion(true, false);
77 message_loop()->PostTask( 77 message_loop()->PostTask(
78 FROM_HERE, 78 FROM_HERE,
79 base::Bind(&BackgroundThread::DoDeleteProducer, object, &completion)); 79 base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion));
80 completion.Wait(); 80 completion.Wait();
81 } 81 }
82 82
83 void DeleteConsumer(Consumer* object) { 83 void DeleteArrow(Arrow* object) {
84 WaitableEvent completion(true, false); 84 WaitableEvent completion(true, false);
85 message_loop()->PostTask( 85 message_loop()->PostTask(
86 FROM_HERE, 86 FROM_HERE,
87 base::Bind(&BackgroundThread::DoDeleteConsumer, object, &completion)); 87 base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion));
88 completion.Wait(); 88 completion.Wait();
89 } 89 }
90 90
91 Producer* DeRef(const Consumer* consumer) { 91 Target* DeRef(const Arrow* arrow) {
92 WaitableEvent completion(true, false); 92 WaitableEvent completion(true, false);
93 Producer* result = NULL; 93 Target* result = NULL;
94 message_loop()->PostTask( 94 message_loop()->PostTask(
95 FROM_HERE, 95 FROM_HERE,
96 base::Bind(&BackgroundThread::DoDeRef, consumer, &result, &completion)); 96 base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion));
97 completion.Wait(); 97 completion.Wait();
98 return result; 98 return result;
99 } 99 }
100 100
101 protected: 101 protected:
102 static void DoCreateFromConsumer(Consumer** consumer, 102 static void DoCreateFromArrow(Arrow** arrow,
103 const Consumer* other, 103 const Arrow* other,
104 WaitableEvent* completion) { 104 WaitableEvent* completion) {
105 *consumer = new Consumer; 105 *arrow = new Arrow;
106 **consumer = *other; 106 **arrow = *other;
107 completion->Signal(); 107 completion->Signal();
108 } 108 }
109 109
110 static void DoCreateFromProducer(Consumer** consumer, 110 static void DoCreateFromTarget(Arrow** arrow,
111 Producer* producer, 111 Target* target,
112 WaitableEvent* completion) { 112 WaitableEvent* completion) {
113 *consumer = new Consumer; 113 *arrow = new Arrow;
114 (*consumer)->producer = producer->AsWeakPtr(); 114 (*arrow)->target = target->AsWeakPtr();
115 completion->Signal(); 115 completion->Signal();
116 } 116 }
117 117
118 static void DoDeRef(const Consumer* consumer, 118 static void DoDeRef(const Arrow* arrow,
119 Producer** result, 119 Target** result,
120 WaitableEvent* completion) { 120 WaitableEvent* completion) {
121 *result = consumer->producer.get(); 121 *result = arrow->target.get();
122 completion->Signal(); 122 completion->Signal();
123 } 123 }
124 124
125 static void DoDeleteProducer(Producer* object, WaitableEvent* completion) { 125 static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
126 delete object; 126 delete object;
127 completion->Signal(); 127 completion->Signal();
128 } 128 }
129 129
130 static void DoDeleteConsumer(Consumer* object, WaitableEvent* completion) { 130 static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
131 delete object; 131 delete object;
132 completion->Signal(); 132 completion->Signal();
133 } 133 }
134 }; 134 };
135 135
136 } // namespace 136 } // namespace
137 137
138 TEST(WeakPtrTest, Basic) { 138 TEST(WeakPtrFactoryTest, Basic) {
139 int data; 139 int data;
140 WeakPtrFactory<int> factory(&data); 140 WeakPtrFactory<int> factory(&data);
141 WeakPtr<int> ptr = factory.GetWeakPtr(); 141 WeakPtr<int> ptr = factory.GetWeakPtr();
142 EXPECT_EQ(&data, ptr.get()); 142 EXPECT_EQ(&data, ptr.get());
143 } 143 }
144 144
145 TEST(WeakPtrTest, Comparison) { 145 TEST(WeakPtrFactoryTest, Comparison) {
146 int data; 146 int data;
147 WeakPtrFactory<int> factory(&data); 147 WeakPtrFactory<int> factory(&data);
148 WeakPtr<int> ptr = factory.GetWeakPtr(); 148 WeakPtr<int> ptr = factory.GetWeakPtr();
149 WeakPtr<int> ptr2 = ptr; 149 WeakPtr<int> ptr2 = ptr;
150 EXPECT_TRUE(ptr == ptr2); 150 EXPECT_TRUE(ptr == ptr2);
151 } 151 }
152 152
153 TEST(WeakPtrTest, OutOfScope) { 153 TEST(WeakPtrFactoryTest, OutOfScope) {
154 WeakPtr<int> ptr; 154 WeakPtr<int> ptr;
155 EXPECT_TRUE(ptr.get() == NULL); 155 EXPECT_TRUE(ptr.get() == NULL);
156 { 156 {
157 int data; 157 int data;
158 WeakPtrFactory<int> factory(&data); 158 WeakPtrFactory<int> factory(&data);
159 ptr = factory.GetWeakPtr(); 159 ptr = factory.GetWeakPtr();
160 } 160 }
161 EXPECT_TRUE(ptr.get() == NULL); 161 EXPECT_TRUE(ptr.get() == NULL);
162 } 162 }
163 163
164 TEST(WeakPtrTest, Multiple) { 164 TEST(WeakPtrFactoryTest, Multiple) {
165 WeakPtr<int> a, b; 165 WeakPtr<int> a, b;
166 { 166 {
167 int data; 167 int data;
168 WeakPtrFactory<int> factory(&data); 168 WeakPtrFactory<int> factory(&data);
169 a = factory.GetWeakPtr(); 169 a = factory.GetWeakPtr();
170 b = factory.GetWeakPtr(); 170 b = factory.GetWeakPtr();
171 EXPECT_EQ(&data, a.get()); 171 EXPECT_EQ(&data, a.get());
172 EXPECT_EQ(&data, b.get()); 172 EXPECT_EQ(&data, b.get());
173 } 173 }
174 EXPECT_TRUE(a.get() == NULL); 174 EXPECT_TRUE(a.get() == NULL);
175 EXPECT_TRUE(b.get() == NULL); 175 EXPECT_TRUE(b.get() == NULL);
176 } 176 }
177 177
178 TEST(WeakPtrTest, MultipleStaged) { 178 TEST(WeakPtrFactoryTest, MultipleStaged) {
179 WeakPtr<int> a; 179 WeakPtr<int> a;
180 { 180 {
181 int data; 181 int data;
182 WeakPtrFactory<int> factory(&data); 182 WeakPtrFactory<int> factory(&data);
183 a = factory.GetWeakPtr(); 183 a = factory.GetWeakPtr();
184 { 184 {
185 WeakPtr<int> b = factory.GetWeakPtr(); 185 WeakPtr<int> b = factory.GetWeakPtr();
186 } 186 }
187 EXPECT_TRUE(a.get() != NULL); 187 EXPECT_TRUE(a.get() != NULL);
188 } 188 }
189 EXPECT_TRUE(a.get() == NULL); 189 EXPECT_TRUE(a.get() == NULL);
190 } 190 }
191 191
192 TEST(WeakPtrTest, UpCast) { 192 TEST(WeakPtrFactoryTest, Dereference) {
193 Base data;
194 data.member = "123456";
195 WeakPtrFactory<Base> factory(&data);
196 WeakPtr<Base> ptr = factory.GetWeakPtr();
197 EXPECT_EQ(&data, ptr.get());
198 EXPECT_EQ(data.member, (*ptr).member);
199 EXPECT_EQ(data.member, ptr->member);
200 }
201
202 TEST(WeakPtrFactoryTest, UpCast) {
193 Derived data; 203 Derived data;
194 WeakPtrFactory<Derived> factory(&data); 204 WeakPtrFactory<Derived> factory(&data);
195 WeakPtr<Base> ptr = factory.GetWeakPtr(); 205 WeakPtr<Base> ptr = factory.GetWeakPtr();
196 ptr = factory.GetWeakPtr(); 206 ptr = factory.GetWeakPtr();
197 EXPECT_EQ(ptr.get(), &data); 207 EXPECT_EQ(ptr.get(), &data);
198 } 208 }
199 209
200 TEST(WeakPtrTest, SupportsWeakPtr) { 210 TEST(WeakPtrTest, SupportsWeakPtr) {
201 Producer f; 211 Target f;
202 WeakPtr<Producer> ptr = f.AsWeakPtr(); 212 WeakPtr<Target> ptr = f.AsWeakPtr();
203 EXPECT_EQ(&f, ptr.get()); 213 EXPECT_EQ(&f, ptr.get());
204 } 214 }
205 215
206 TEST(WeakPtrTest, DerivedProducer) { 216 TEST(WeakPtrTest, DerivedTarget) {
207 DerivedProducer f; 217 DerivedTarget f;
208 WeakPtr<DerivedProducer> ptr = AsWeakPtr(&f); 218 WeakPtr<DerivedTarget> ptr = AsWeakPtr(&f);
209 EXPECT_EQ(&f, ptr.get()); 219 EXPECT_EQ(&f, ptr.get());
210 } 220 }
211 221
212 TEST(WeakPtrTest, InvalidateWeakPtrs) { 222 TEST(WeakPtrTest, InvalidateWeakPtrs) {
213 int data; 223 int data;
214 WeakPtrFactory<int> factory(&data); 224 WeakPtrFactory<int> factory(&data);
215 WeakPtr<int> ptr = factory.GetWeakPtr(); 225 WeakPtr<int> ptr = factory.GetWeakPtr();
216 EXPECT_EQ(&data, ptr.get()); 226 EXPECT_EQ(&data, ptr.get());
217 EXPECT_TRUE(factory.HasWeakPtrs()); 227 EXPECT_TRUE(factory.HasWeakPtrs());
218 factory.InvalidateWeakPtrs(); 228 factory.InvalidateWeakPtrs();
219 EXPECT_TRUE(ptr.get() == NULL); 229 EXPECT_TRUE(ptr.get() == NULL);
220 EXPECT_FALSE(factory.HasWeakPtrs()); 230 EXPECT_FALSE(factory.HasWeakPtrs());
221 } 231 }
222 232
223 TEST(WeakPtrTest, HasWeakPtrs) { 233 TEST(WeakPtrTest, HasWeakPtrs) {
224 int data; 234 int data;
225 WeakPtrFactory<int> factory(&data); 235 WeakPtrFactory<int> factory(&data);
226 { 236 {
227 WeakPtr<int> ptr = factory.GetWeakPtr(); 237 WeakPtr<int> ptr = factory.GetWeakPtr();
228 EXPECT_TRUE(factory.HasWeakPtrs()); 238 EXPECT_TRUE(factory.HasWeakPtrs());
229 } 239 }
230 EXPECT_FALSE(factory.HasWeakPtrs()); 240 EXPECT_FALSE(factory.HasWeakPtrs());
231 } 241 }
232 242
233 TEST(WeakPtrTest, SingleThreaded1) { 243 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
234 // Test that it is OK to create a class that supports weak references on one 244 // Test that it is OK to create an object that supports WeakPtr on one thread,
235 // thread, but use it on another. This tests that we do not trip runtime 245 // but uses it on another. This tests that we do not trip runtime checks that
Ryan Sleevi 2012/07/10 00:06:44 nit: uses -> use (since this is an active statemen
kaiwang 2012/07/10 22:21:19 Done.
236 // checks that ensure that a weak reference is not used by multiple threads. 246 // ensure that a WeakPtr is not used by multiple threads.
237 scoped_ptr<Producer> producer(OffThreadObjectCreator<Producer>::NewObject()); 247 scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
238 WeakPtr<Producer> weak_producer = producer->AsWeakPtr(); 248 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
239 EXPECT_EQ(producer.get(), weak_producer.get()); 249 EXPECT_EQ(target.get(), weak_ptr.get());
240 } 250 }
241 251
242 TEST(WeakPtrTest, SingleThreaded2) { 252 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
243 // Test that it is OK to create a class that has a WeakPtr member on one 253 // Test that it is OK to create an object that has a WeakPtr member on one
244 // thread, but use it on another. This tests that we do not trip runtime 254 // thread, but use it on another. This tests that we do not trip runtime
245 // checks that ensure that a weak reference is not used by multiple threads. 255 // checks that ensure that a WeakPtr is not used by multiple threads.
246 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject()); 256 scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
247 Producer producer; 257 Target target;
248 consumer->producer = producer.AsWeakPtr(); 258 arrow->target = target.AsWeakPtr();
249 EXPECT_EQ(&producer, consumer->producer.get()); 259 EXPECT_EQ(&target, arrow->target.get());
250 } 260 }
251 261
252 TEST(WeakPtrTest, MoveOwnershipImplicit) { 262 TEST(WeakPtrTest, MoveOwnershipImplicitly) {
253 // Move object ownership to other thread by releasing all weak pointers 263 // Move object ownership to other thread by releasing all weak pointers
254 // on the original thread first. Establishing weak pointers on a different 264 // on the original thread first. Establishing weak pointers on a different
255 // thread after previous pointers have been destroyed implicitly reattaches 265 // thread after previous pointers have been destroyed implicitly reattaches
256 // the thread checks. 266 // the thread checks.
257 // - Thread A creates object and weak pointer 267 // - Main thread creates object and weak pointer
258 // - Thread A deletes the weak pointer 268 // - Main thread deletes the weak pointer, then the thread ownership of the
259 // - Thread B creates weak pointer 269 // object can be implicitly moved.
260 // - Thread B derefs weak pointer 270 // - Background thread creates weak pointer(and implicitly owns the object)
261 // - Thread B deletes object 271 // - Background thread derefs weak pointer
262 BackgroundThread thread; 272 // - Background thread deletes object
263 thread.Start(); 273 // - Background thread deletes weak pointer
264 Producer* producer = new Producer(); 274 BackgroundThread background;
275 background.Start();
276 Target* target = new Target();
265 { 277 {
266 WeakPtr<Producer> weak_ptr = producer->AsWeakPtr(); 278 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
267 } 279 }
268 Consumer* consumer; 280 Arrow* arrow;
269 thread.CreateConsumerFromProducer(&consumer, producer); 281 background.CreateArrowFromTarget(&arrow, target);
270 EXPECT_EQ(thread.DeRef(consumer), producer); 282 EXPECT_EQ(background.DeRef(arrow), target);
271 thread.DeleteProducer(producer); 283 background.DeleteTarget(target);
272 thread.DeleteConsumer(consumer); 284 background.DeleteArrow(arrow);
273 } 285 }
274 286
275 TEST(WeakPtrTest, MoveOwnershipExplicit) { 287 TEST(WeakPtrTest, MoveOwnershipExplicitlyObjectNotReferenced) {
276 // Test that we do not trip any checks if we establish weak references 288 // Case 1: The target is not bound to any thread yet. So calling
277 // on one thread and delete the object on another thread after explicit 289 // DetachFromThread() is a no-op.
278 // detachment. 290 Target target;
279 // - Thread A creates object 291 target.DetachFromThread();
280 // - Thread B creates weak pointer 292
281 // - Thread B releases weak pointer 293 // Case 2: The target is bound to main thread but no WeakPtr is pointing to
282 // - Detach owner from Thread B 294 // it. In this case, it will be re-bound to any thread trying to get a
283 // - Thread A destroys object 295 // WeakPtr pointing to it. So detach function call is again no-op.
284 BackgroundThread thread; 296 {
285 thread.Start(); 297 WeakPtr<Target> weak_ptr = target.AsWeakPtr();
286 Producer producer; 298 }
287 Consumer* consumer; 299 target.DetachFromThread();
288 thread.CreateConsumerFromProducer(&consumer, &producer); 300 }
289 EXPECT_EQ(thread.DeRef(consumer), &producer); 301
290 thread.DeleteConsumer(consumer); 302 TEST(WeakPtrTest, MoveOwnershipExplicitly) {
291 producer.DetachFromThread(); 303 // Test that we do not trip any checks if we establish WeakPtr on one thread
304 // and delete the object on another thread after explicit detachment.
305 // - Main thread creates object
306 // - Background thread creates weak pointer(and implicitly owns the object)
307 // - Object detach from background thread
308 // - Main thread destroys object
309 BackgroundThread background;
310 background.Start();
311 Target target;
312 Arrow* arrow;
313
314 background.CreateArrowFromTarget(&arrow, &target);
315 EXPECT_EQ(background.DeRef(arrow), &target);
316 target.DetachFromThread();
317 // Detached target getting destructed will not cause thread ownership
318 // violation.
292 } 319 }
293 320
294 TEST(WeakPtrTest, ThreadARefOutlivesThreadBRef) { 321 TEST(WeakPtrTest, ThreadARefOutlivesThreadBRef) {
295 // Originating thread has a WeakPtr that outlives others. 322 // Originating thread has a WeakPtr that outlives others.
296 // - Thread A creates WeakPtr<> and passes copy to Thread B 323 // - Main thread creates a WeakPtr
297 // - Destruct the pointer on Thread B 324 // - Background thread creates a WeakPtr copy from the one in main thread
298 // - Destruct the pointer on Thread A 325 // - Destruct the WeakPtr on background thread
299 BackgroundThread thread; 326 // - Destruct the WeakPtr on main thread
300 thread.Start(); 327
301 Producer producer; 328 BackgroundThread background;
302 Consumer consumer; 329 background.Start();
303 consumer.producer = producer.AsWeakPtr(); 330
304 Consumer* consumer_copy; 331 Target target;
305 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); 332 Arrow arrow;
306 EXPECT_EQ(consumer_copy->producer, &producer); 333 arrow.target = target.AsWeakPtr();
307 thread.DeleteConsumer(consumer_copy); 334
335 Arrow* arrow_copy;
336 background.CreateArrowFromArrow(&arrow_copy, &arrow);
337 EXPECT_EQ(arrow_copy->target, &target);
338 background.DeleteArrow(arrow_copy);
308 } 339 }
309 340
310 TEST(WeakPtrTest, ThreadBRefOutlivesThreadARef) { 341 TEST(WeakPtrTest, ThreadBRefOutlivesThreadARef) {
311 // Originating thread drops all references before another thread. 342 // Originating thread drops all references before another thread.
312 // - Thread A creates WeakPtr<> and passes copy to Thread B 343 // - Main thread creates a WeakPtr and passes copy to background thread
313 // - Destruct the pointer on Thread A 344 // - Destruct the pointer on main thread
314 // - Destruct the pointer on Thread B 345 // - Destruct the pointer on background thread
315 BackgroundThread thread; 346 BackgroundThread background;
316 thread.Start(); 347 background.Start();
317 Producer producer; 348 Target target;
318 Consumer* consumer_copy; 349 Arrow* arrow_copy;
319 { 350 {
320 Consumer consumer; 351 Arrow arrow;
321 consumer.producer = producer.AsWeakPtr(); 352 arrow.target = target.AsWeakPtr();
322 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); 353 background.CreateArrowFromArrow(&arrow_copy, &arrow);
323 } 354 }
324 EXPECT_EQ(consumer_copy->producer, &producer); 355 EXPECT_EQ(arrow_copy->target, &target);
325 thread.DeleteConsumer(consumer_copy); 356 background.DeleteArrow(arrow_copy);
326 } 357 }
327 358
328 TEST(WeakPtrTest, OwnerThreadDeletesObject) { 359 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
329 // Originating thread invalidates WeakPtrs while its held by other thread. 360 // Originating thread invalidates WeakPtrs while its held by other thread.
330 // - Thread A creates WeakPtr<> and passes Copy to Thread B 361 // - Main thread creates WeakPtr and passes Copy to background thread
331 // - WeakReferenceOwner gets destroyed on Thread A 362 // - Object gets destroyed on main thread
363 // (invalidates WeakPtr on background thread)
332 // - WeakPtr gets destroyed on Thread B 364 // - WeakPtr gets destroyed on Thread B
333 BackgroundThread thread; 365 BackgroundThread background;
334 thread.Start(); 366 background.Start();
335 Consumer* consumer_copy; 367 Arrow* arrow_copy;
336 { 368 {
337 Producer producer; 369 Target target;
338 Consumer consumer; 370 Arrow arrow;
339 consumer.producer = producer.AsWeakPtr(); 371 arrow.target = target.AsWeakPtr();
340 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); 372 background.CreateArrowFromArrow(&arrow_copy, &arrow);
341 } 373 }
342 EXPECT_TRUE(consumer_copy->producer == NULL); 374 EXPECT_TRUE(arrow_copy->target == NULL);
343 thread.DeleteConsumer(consumer_copy); 375 background.DeleteArrow(arrow_copy);
344 } 376 }
345 377
346 TEST(WeakPtrTest, Dereference) { 378 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
347 Base data; 379 // Main thread creates a Target object.
348 data.member = "123456"; 380 Target target;
349 WeakPtrFactory<Base> factory(&data); 381 // Main thread creates a arrow referencing the Target.
350 WeakPtr<Base> ptr = factory.GetWeakPtr(); 382 Arrow* arrow = new Arrow();
351 EXPECT_EQ(&data, ptr.get()); 383 arrow->target = target.AsWeakPtr();
352 EXPECT_EQ(data.member, (*ptr).member); 384
353 EXPECT_EQ(data.member, ptr->member); 385 // Background can delete arrow (as well as the WeakPtr inside).
386 BackgroundThread background;
387 background.Start();
388 background.DeleteArrow(arrow);
354 } 389 }
355 390
391 #ifndef NDEBUG // Thread ownership is only checked in debug version.
Ryan Sleevi 2012/07/10 00:06:44 This isn't correct It should be #if !defined(NDE
kaiwang 2012/07/10 22:21:19 Done.
392
393 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtr) {
394 // The default value "fast" can not well support multi-threaded tests.
395 // May introduce deadlock on linux.
396 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
397
398 // Main thread creates a Target object.
399 Target target;
400 // Main thread creates a arrow referencing the Target (so target's
401 // thread ownership can not be implicitly moved).
402 Arrow arrow;
403 arrow.target = target.AsWeakPtr();
404
405 // Background thread tries to delete target, which violates thread
406 // ownership.
Ryan Sleevi 2012/07/10 00:06:44 the comments here and on 423 are backwards (this o
kaiwang 2012/07/10 22:21:19 Done.
407 BackgroundThread background;
408 background.Start();
409 ASSERT_DEATH(background.DeRef(&arrow), "");
410 }
411
412 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObject) {
413 // The default value "fast" can not well support multi-threaded tests.
414 // May introduce deadlock on linux.
415 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
416
417 Target* target = new Target();
Ryan Sleevi 2012/07/10 00:06:44 Pretty sure this object will show up in the valgri
kaiwang 2012/07/10 22:21:19 Done.
418 // Main thread creates a arrow referencing the Target (so target's thread
419 // ownership can not be implicitly moved).
420 Arrow arrow;
421 arrow.target = target->AsWeakPtr();
422
423 // Background thread tries to deref target, which violates thread ownership.
424 BackgroundThread background;
425 background.Start();
426 ASSERT_DEATH(background.DeleteTarget(target), "");
427 }
428
429 #endif
430
356 } // namespace base 431 } // namespace base
OLDNEW
« base/memory/weak_ptr.h ('K') | « base/memory/weak_ptr.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698