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

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 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_TRUE(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_TRUE(ptr.get() == NULL);
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_TRUE(ptr.get() == NULL);
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_TRUE(a.get() == NULL);
175 EXPECT_TRUE(b.get() == NULL); 179 EXPECT_TRUE(b.get() == NULL);
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(a.get() != NULL);
188 } 192 }
189 EXPECT_TRUE(a.get() == NULL); 193 EXPECT_TRUE(a.get() == NULL);
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 f;
jar (doing other things) 2012/07/10 23:00:56 Sorry I didn't notice this before... (and this ex
kaiwang 2012/07/11 01:17:05 Done, for 169 and 183, it's just an int. So I thin
202 WeakPtr<Producer> ptr = f.AsWeakPtr(); 216 WeakPtr<Target> ptr = f.AsWeakPtr();
203 EXPECT_EQ(&f, ptr.get()); 217 EXPECT_EQ(&f, ptr.get());
204 } 218 }
205 219
206 TEST(WeakPtrTest, DerivedProducer) { 220 TEST(WeakPtrTest, DerivedTarget) {
207 DerivedProducer f; 221 DerivedTarget f;
208 WeakPtr<DerivedProducer> ptr = AsWeakPtr(&f); 222 WeakPtr<DerivedTarget> ptr = AsWeakPtr(&f);
209 EXPECT_EQ(&f, ptr.get()); 223 EXPECT_EQ(&f, 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_TRUE(ptr.get() == NULL);
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
245 // checks that ensure that a weak reference is not used by multiple threads.
246 scoped_ptr<Consumer> consumer(OffThreadObjectCreator<Consumer>::NewObject());
247 Producer producer;
248 consumer->producer = producer.AsWeakPtr();
249 EXPECT_EQ(&producer, consumer->producer.get());
250 }
251
252 TEST(WeakPtrTest, MoveOwnershipImplicit) {
253 // Move object ownership to other thread by releasing all weak pointers 267 // Move object ownership to other thread by releasing all weak pointers
254 // on the original thread first. Establishing weak pointers on a different 268 // on the original thread first. Establishing weak pointers on a different
255 // thread after previous pointers have been destroyed implicitly reattaches 269 // thread after previous pointers have been destroyed implicitly reattaches
256 // the thread checks. 270 // the thread checks.
257 // - Thread A creates object and weak pointer 271 // - Main thread creates object and weak pointer
258 // - Thread A deletes the weak pointer 272 // - Main thread deletes the weak pointer, then the thread ownership of the
259 // - Thread B creates weak pointer 273 // object can be implicitly moved.
260 // - Thread B derefs weak pointer 274 // - Background thread creates weak pointer(and implicitly owns the object)
261 // - Thread B deletes object 275 // - Background thread derefs weak pointer
262 BackgroundThread thread; 276 // - Background thread deletes object
263 thread.Start(); 277 // - Background thread deletes weak pointer
264 Producer* producer = new Producer(); 278 BackgroundThread background;
265 { 279 background.Start();
266 WeakPtr<Producer> weak_ptr = producer->AsWeakPtr(); 280 Target* target = new Target();
267 } 281 {
268 Consumer* consumer; 282 WeakPtr<Target> weak_ptr = target->AsWeakPtr();
269 thread.CreateConsumerFromProducer(&consumer, producer); 283 }
270 EXPECT_EQ(thread.DeRef(consumer), producer); 284 Arrow* arrow;
271 thread.DeleteProducer(producer); 285 background.CreateArrowFromTarget(&arrow, target);
272 thread.DeleteConsumer(consumer); 286 EXPECT_EQ(background.DeRef(arrow), target);
273 } 287 background.DeleteTarget(target);
274 288 background.DeleteArrow(arrow);
275 TEST(WeakPtrTest, MoveOwnershipExplicit) { 289 }
276 // Test that we do not trip any checks if we establish weak references 290
277 // on one thread and delete the object on another thread after explicit 291 TEST(WeakPtrTest, MoveOwnershipExplicitlyObjectNotReferenced) {
278 // detachment. 292 // Case 1: The target is not bound to any thread yet. So calling
279 // - Thread A creates object 293 // DetachFromThread() is a no-op.
280 // - Thread B creates weak pointer 294 Target target;
281 // - Thread B releases weak pointer 295 target.DetachFromThread();
282 // - Detach owner from Thread B 296
283 // - Thread A destroys object 297 // Case 2: The target is bound to main thread but no WeakPtr is pointing to
284 BackgroundThread thread; 298 // it. In this case, it will be re-bound to any thread trying to get a
285 thread.Start(); 299 // WeakPtr pointing to it. So detach function call is again no-op.
286 Producer producer; 300 {
287 Consumer* consumer; 301 WeakPtr<Target> weak_ptr = target.AsWeakPtr();
288 thread.CreateConsumerFromProducer(&consumer, &producer); 302 }
289 EXPECT_EQ(thread.DeRef(consumer), &producer); 303 target.DetachFromThread();
290 thread.DeleteConsumer(consumer); 304 }
291 producer.DetachFromThread(); 305
292 } 306 TEST(WeakPtrTest, MoveOwnershipExplicitly) {
293 307 // Test that we do not trip any checks if we establish WeakPtr on one thread
294 TEST(WeakPtrTest, ThreadARefOutlivesThreadBRef) { 308 // and delete the object on another thread after explicit detachment.
309 // - Main thread creates object
310 // - Background thread creates weak pointer(and implicitly owns the object)
311 // - Object detach from background thread
312 // - Main thread destroys object
313 BackgroundThread background;
314 background.Start();
315 Target target;
316 Arrow* arrow;
317
318 background.CreateArrowFromTarget(&arrow, &target);
319 EXPECT_EQ(background.DeRef(arrow), &target);
320 target.DetachFromThread();
321 // Detached target getting destructed will not cause thread ownership
322 // violation.
jar (doing other things) 2012/07/10 23:00:56 Will this leak arrow?
kaiwang 2012/07/11 01:17:05 Done.
323 }
324
325 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
295 // Originating thread has a WeakPtr that outlives others. 326 // Originating thread has a WeakPtr that outlives others.
296 // - Thread A creates WeakPtr<> and passes copy to Thread B 327 // - Main thread creates a WeakPtr
297 // - Destruct the pointer on Thread B 328 // - Background thread creates a WeakPtr copy from the one in main thread
298 // - Destruct the pointer on Thread A 329 // - Destruct the WeakPtr on background thread
299 BackgroundThread thread; 330 // - Destruct the WeakPtr on main thread
300 thread.Start(); 331 BackgroundThread background;
301 Producer producer; 332 background.Start();
302 Consumer consumer; 333
303 consumer.producer = producer.AsWeakPtr(); 334 Target target;
304 Consumer* consumer_copy; 335 Arrow arrow;
305 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); 336 arrow.target = target.AsWeakPtr();
306 EXPECT_EQ(consumer_copy->producer, &producer); 337
307 thread.DeleteConsumer(consumer_copy); 338 Arrow* arrow_copy;
308 } 339 background.CreateArrowFromArrow(&arrow_copy, &arrow);
309 340 EXPECT_EQ(arrow_copy->target, &target);
310 TEST(WeakPtrTest, ThreadBRefOutlivesThreadARef) { 341 background.DeleteArrow(arrow_copy);
342 }
343
344 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
311 // Originating thread drops all references before another thread. 345 // Originating thread drops all references before another thread.
312 // - Thread A creates WeakPtr<> and passes copy to Thread B 346 // - Main thread creates a WeakPtr and passes copy to background thread
313 // - Destruct the pointer on Thread A 347 // - Destruct the pointer on main thread
314 // - Destruct the pointer on Thread B 348 // - Destruct the pointer on background thread
315 BackgroundThread thread; 349 BackgroundThread background;
316 thread.Start(); 350 background.Start();
317 Producer producer; 351
318 Consumer* consumer_copy; 352 Target target;
319 { 353 Arrow* arrow_copy;
320 Consumer consumer; 354 {
321 consumer.producer = producer.AsWeakPtr(); 355 Arrow arrow;
322 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); 356 arrow.target = target.AsWeakPtr();
323 } 357 background.CreateArrowFromArrow(&arrow_copy, &arrow);
324 EXPECT_EQ(consumer_copy->producer, &producer); 358 }
325 thread.DeleteConsumer(consumer_copy); 359 EXPECT_EQ(arrow_copy->target, &target);
360 background.DeleteArrow(arrow_copy);
326 } 361 }
327 362
328 TEST(WeakPtrTest, OwnerThreadDeletesObject) { 363 TEST(WeakPtrTest, OwnerThreadDeletesObject) {
329 // Originating thread invalidates WeakPtrs while its held by other thread. 364 // Originating thread invalidates WeakPtrs while its held by other thread.
330 // - Thread A creates WeakPtr<> and passes Copy to Thread B 365 // - Main thread creates WeakPtr and passes Copy to background thread
331 // - WeakReferenceOwner gets destroyed on Thread A 366 // - Object gets destroyed on main thread
367 // (invalidates WeakPtr on background thread)
332 // - WeakPtr gets destroyed on Thread B 368 // - WeakPtr gets destroyed on Thread B
333 BackgroundThread thread; 369 BackgroundThread background;
334 thread.Start(); 370 background.Start();
335 Consumer* consumer_copy; 371 Arrow* arrow_copy;
336 { 372 {
337 Producer producer; 373 Target target;
338 Consumer consumer; 374 Arrow arrow;
339 consumer.producer = producer.AsWeakPtr(); 375 arrow.target = target.AsWeakPtr();
340 thread.CreateConsumerFromConsumer(&consumer_copy, &consumer); 376 background.CreateArrowFromArrow(&arrow_copy, &arrow);
341 } 377 }
342 EXPECT_TRUE(consumer_copy->producer == NULL); 378 EXPECT_TRUE(arrow_copy->target == NULL);
343 thread.DeleteConsumer(consumer_copy); 379 background.DeleteArrow(arrow_copy);
344 } 380 }
345 381
346 TEST(WeakPtrTest, Dereference) { 382 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
347 Base data; 383 // Main thread creates a Target object.
348 data.member = "123456"; 384 Target target;
349 WeakPtrFactory<Base> factory(&data); 385 // Main thread creates an arrow referencing the Target.
350 WeakPtr<Base> ptr = factory.GetWeakPtr(); 386 Arrow* arrow = new Arrow();
351 EXPECT_EQ(&data, ptr.get()); 387 arrow->target = target.AsWeakPtr();
352 EXPECT_EQ(data.member, (*ptr).member); 388
353 EXPECT_EQ(data.member, ptr->member); 389 // Background can delete arrow (as well as the WeakPtr inside).
354 } 390 BackgroundThread background;
391 background.Start();
392 background.DeleteArrow(arrow);
393 }
394
395 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
396
397 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
398 // The default value "fast" can not well support multi-threaded tests
399 // (introduces deadlock on linux).
Ryan Sleevi 2012/07/10 22:41:54 nit: s/can not well/does not/ s/linux/Linux/ Same
kaiwang 2012/07/11 01:17:05 Done.
400 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
401
402 BackgroundThread background;
403 background.Start();
404
405 // Main thread creates a Target object.
406 Target target;
407 // Main thread creates an arrow referencing the Target.
408 Arrow arrow;
409 arrow.target = target.AsWeakPtr();
410
411 // Background copies the WeakPtr.
412 Arrow* arrow_copy;
413 background.CreateArrowFromArrow(&arrow_copy, &arrow);
Ryan Sleevi 2012/07/10 22:41:54 You're now leaking the arrow_copy, I believe. This
kaiwang 2012/07/11 01:17:05 since we are modifying the pointer in background t
414
415 // The copy is still bound to main thread so I can deref.
416 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
417
418 // Although background thread created the copy, it can not deref the copied
419 // WeakPtr.
420 ASSERT_DEATH(background.DeRef(arrow_copy), "");
421 }
422
423 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtr) {
424 // The default value "fast" can not well support multi-threaded tests
425 // (introduces deadlock on linux).
426 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
427
428 // Main thread creates a Target object.
429 Target target;
430 // Main thread creates an arrow referencing the Target (so target's
431 // thread ownership can not be implicitly moved).
432 Arrow arrow;
433 arrow.target = target.AsWeakPtr();
434
435 // Background thread tries to deref target, which violates thread ownership.
436 BackgroundThread background;
437 background.Start();
438 ASSERT_DEATH(background.DeRef(&arrow), "");
439 }
440
441 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObject) {
442 // The default value "fast" can not well support multi-threaded tests
443 // (introduces deadlock on linux).
444 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
445
446 scoped_ptr<Target> target(new Target());
447 // Main thread creates an arrow referencing the Target (so target's thread
448 // ownership can not be implicitly moved).
449 Arrow arrow;
450 arrow.target = target->AsWeakPtr();
451
452 // Background thread tries to delete target, which violates thread ownership.
453 BackgroundThread background;
454 background.Start();
455 ASSERT_DEATH(background.DeleteTarget(target.release()), "");
456 }
457
458 #endif
355 459
356 } // namespace base 460 } // 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