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 <memory> | 7 #include <memory> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/debug/leak_annotations.h" | 11 #include "base/debug/leak_annotations.h" |
12 #include "base/location.h" | 12 #include "base/location.h" |
13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
14 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
15 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
17 | 17 |
18 namespace base { | 18 namespace base { |
19 namespace { | 19 namespace { |
20 | 20 |
| 21 WeakPtr<int> PassThru(WeakPtr<int> ptr) { |
| 22 return ptr; |
| 23 } |
| 24 |
21 template <class T> | 25 template <class T> |
22 class OffThreadObjectCreator { | 26 class OffThreadObjectCreator { |
23 public: | 27 public: |
24 static T* NewObject() { | 28 static T* NewObject() { |
25 T* result; | 29 T* result; |
26 { | 30 { |
27 Thread creator_thread("creator_thread"); | 31 Thread creator_thread("creator_thread"); |
28 creator_thread.Start(); | 32 creator_thread.Start(); |
29 creator_thread.task_runner()->PostTask( | 33 creator_thread.task_runner()->PostTask( |
30 FROM_HERE, base::Bind(OffThreadObjectCreator::CreateObject, &result)); | 34 FROM_HERE, base::Bind(OffThreadObjectCreator::CreateObject, &result)); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 void DeleteArrow(Arrow* object) { | 111 void DeleteArrow(Arrow* object) { |
108 WaitableEvent completion(true, false); | 112 WaitableEvent completion(true, false); |
109 task_runner()->PostTask( | 113 task_runner()->PostTask( |
110 FROM_HERE, | 114 FROM_HERE, |
111 base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion)); | 115 base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion)); |
112 completion.Wait(); | 116 completion.Wait(); |
113 } | 117 } |
114 | 118 |
115 Target* DeRef(const Arrow* arrow) { | 119 Target* DeRef(const Arrow* arrow) { |
116 WaitableEvent completion(true, false); | 120 WaitableEvent completion(true, false); |
117 Target* result = NULL; | 121 Target* result = nullptr; |
118 task_runner()->PostTask(FROM_HERE, base::Bind(&BackgroundThread::DoDeRef, | 122 task_runner()->PostTask(FROM_HERE, base::Bind(&BackgroundThread::DoDeRef, |
119 arrow, &result, &completion)); | 123 arrow, &result, &completion)); |
120 completion.Wait(); | 124 completion.Wait(); |
121 return result; | 125 return result; |
122 } | 126 } |
123 | 127 |
124 protected: | 128 protected: |
125 static void DoCreateArrowFromArrow(Arrow** arrow, | 129 static void DoCreateArrowFromArrow(Arrow** arrow, |
126 const Arrow* other, | 130 const Arrow* other, |
127 WaitableEvent* completion) { | 131 WaitableEvent* completion) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 TEST(WeakPtrFactoryTest, Comparison) { | 191 TEST(WeakPtrFactoryTest, Comparison) { |
188 int data; | 192 int data; |
189 WeakPtrFactory<int> factory(&data); | 193 WeakPtrFactory<int> factory(&data); |
190 WeakPtr<int> ptr = factory.GetWeakPtr(); | 194 WeakPtr<int> ptr = factory.GetWeakPtr(); |
191 WeakPtr<int> ptr2 = ptr; | 195 WeakPtr<int> ptr2 = ptr; |
192 EXPECT_EQ(ptr.get(), ptr2.get()); | 196 EXPECT_EQ(ptr.get(), ptr2.get()); |
193 } | 197 } |
194 | 198 |
195 TEST(WeakPtrFactoryTest, OutOfScope) { | 199 TEST(WeakPtrFactoryTest, OutOfScope) { |
196 WeakPtr<int> ptr; | 200 WeakPtr<int> ptr; |
197 EXPECT_EQ(NULL, ptr.get()); | 201 EXPECT_EQ(nullptr, ptr.get()); |
198 { | 202 { |
199 int data; | 203 int data; |
200 WeakPtrFactory<int> factory(&data); | 204 WeakPtrFactory<int> factory(&data); |
201 ptr = factory.GetWeakPtr(); | 205 ptr = factory.GetWeakPtr(); |
202 } | 206 } |
203 EXPECT_EQ(NULL, ptr.get()); | 207 EXPECT_EQ(nullptr, ptr.get()); |
204 } | 208 } |
205 | 209 |
206 TEST(WeakPtrFactoryTest, Multiple) { | 210 TEST(WeakPtrFactoryTest, Multiple) { |
207 WeakPtr<int> a, b; | 211 WeakPtr<int> a, b; |
208 { | 212 { |
209 int data; | 213 int data; |
210 WeakPtrFactory<int> factory(&data); | 214 WeakPtrFactory<int> factory(&data); |
211 a = factory.GetWeakPtr(); | 215 a = factory.GetWeakPtr(); |
212 b = factory.GetWeakPtr(); | 216 b = factory.GetWeakPtr(); |
213 EXPECT_EQ(&data, a.get()); | 217 EXPECT_EQ(&data, a.get()); |
214 EXPECT_EQ(&data, b.get()); | 218 EXPECT_EQ(&data, b.get()); |
215 } | 219 } |
216 EXPECT_EQ(NULL, a.get()); | 220 EXPECT_EQ(nullptr, a.get()); |
217 EXPECT_EQ(NULL, b.get()); | 221 EXPECT_EQ(nullptr, b.get()); |
218 } | 222 } |
219 | 223 |
220 TEST(WeakPtrFactoryTest, MultipleStaged) { | 224 TEST(WeakPtrFactoryTest, MultipleStaged) { |
221 WeakPtr<int> a; | 225 WeakPtr<int> a; |
222 { | 226 { |
223 int data; | 227 int data; |
224 WeakPtrFactory<int> factory(&data); | 228 WeakPtrFactory<int> factory(&data); |
225 a = factory.GetWeakPtr(); | 229 a = factory.GetWeakPtr(); |
226 { | 230 { |
227 WeakPtr<int> b = factory.GetWeakPtr(); | 231 WeakPtr<int> b = factory.GetWeakPtr(); |
228 } | 232 } |
229 EXPECT_TRUE(NULL != a.get()); | 233 EXPECT_NE(nullptr, a.get()); |
230 } | 234 } |
231 EXPECT_EQ(NULL, a.get()); | 235 EXPECT_EQ(nullptr, a.get()); |
232 } | 236 } |
233 | 237 |
234 TEST(WeakPtrFactoryTest, Dereference) { | 238 TEST(WeakPtrFactoryTest, Dereference) { |
235 Base data; | 239 Base data; |
236 data.member = "123456"; | 240 data.member = "123456"; |
237 WeakPtrFactory<Base> factory(&data); | 241 WeakPtrFactory<Base> factory(&data); |
238 WeakPtr<Base> ptr = factory.GetWeakPtr(); | 242 WeakPtr<Base> ptr = factory.GetWeakPtr(); |
239 EXPECT_EQ(&data, ptr.get()); | 243 EXPECT_EQ(&data, ptr.get()); |
240 EXPECT_EQ(data.member, (*ptr).member); | 244 EXPECT_EQ(data.member, (*ptr).member); |
241 EXPECT_EQ(data.member, ptr->member); | 245 EXPECT_EQ(data.member, ptr->member); |
242 } | 246 } |
243 | 247 |
244 TEST(WeakPtrFactoryTest, UpCast) { | 248 TEST(WeakPtrFactoryTest, UpCast) { |
245 Derived data; | 249 Derived data; |
246 WeakPtrFactory<Derived> factory(&data); | 250 WeakPtrFactory<Derived> factory(&data); |
247 WeakPtr<Base> ptr = factory.GetWeakPtr(); | 251 WeakPtr<Base> ptr = factory.GetWeakPtr(); |
248 ptr = factory.GetWeakPtr(); | 252 ptr = factory.GetWeakPtr(); |
249 EXPECT_EQ(ptr.get(), &data); | 253 EXPECT_EQ(ptr.get(), &data); |
250 } | 254 } |
251 | 255 |
| 256 TEST(WeakPtrTest, ConstructFromNullptr) { |
| 257 WeakPtr<int> ptr = PassThru(nullptr); |
| 258 EXPECT_EQ(nullptr, ptr.get()); |
| 259 } |
| 260 |
252 TEST(WeakPtrTest, SupportsWeakPtr) { | 261 TEST(WeakPtrTest, SupportsWeakPtr) { |
253 Target target; | 262 Target target; |
254 WeakPtr<Target> ptr = target.AsWeakPtr(); | 263 WeakPtr<Target> ptr = target.AsWeakPtr(); |
255 EXPECT_EQ(&target, ptr.get()); | 264 EXPECT_EQ(&target, ptr.get()); |
256 } | 265 } |
257 | 266 |
258 TEST(WeakPtrTest, DerivedTarget) { | 267 TEST(WeakPtrTest, DerivedTarget) { |
259 DerivedTarget target; | 268 DerivedTarget target; |
260 WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target); | 269 WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target); |
261 EXPECT_EQ(&target, ptr.get()); | 270 EXPECT_EQ(&target, ptr.get()); |
(...skipping 30 matching lines...) Expand all Loading... |
292 } | 301 } |
293 } | 302 } |
294 | 303 |
295 TEST(WeakPtrTest, InvalidateWeakPtrs) { | 304 TEST(WeakPtrTest, InvalidateWeakPtrs) { |
296 int data; | 305 int data; |
297 WeakPtrFactory<int> factory(&data); | 306 WeakPtrFactory<int> factory(&data); |
298 WeakPtr<int> ptr = factory.GetWeakPtr(); | 307 WeakPtr<int> ptr = factory.GetWeakPtr(); |
299 EXPECT_EQ(&data, ptr.get()); | 308 EXPECT_EQ(&data, ptr.get()); |
300 EXPECT_TRUE(factory.HasWeakPtrs()); | 309 EXPECT_TRUE(factory.HasWeakPtrs()); |
301 factory.InvalidateWeakPtrs(); | 310 factory.InvalidateWeakPtrs(); |
302 EXPECT_EQ(NULL, ptr.get()); | 311 EXPECT_EQ(nullptr, ptr.get()); |
303 EXPECT_FALSE(factory.HasWeakPtrs()); | 312 EXPECT_FALSE(factory.HasWeakPtrs()); |
304 | 313 |
305 // Test that the factory can create new weak pointers after a | 314 // Test that the factory can create new weak pointers after a |
306 // InvalidateWeakPtrs call, and they remain valid until the next | 315 // InvalidateWeakPtrs call, and they remain valid until the next |
307 // InvalidateWeakPtrs call. | 316 // InvalidateWeakPtrs call. |
308 WeakPtr<int> ptr2 = factory.GetWeakPtr(); | 317 WeakPtr<int> ptr2 = factory.GetWeakPtr(); |
309 EXPECT_EQ(&data, ptr2.get()); | 318 EXPECT_EQ(&data, ptr2.get()); |
310 EXPECT_TRUE(factory.HasWeakPtrs()); | 319 EXPECT_TRUE(factory.HasWeakPtrs()); |
311 factory.InvalidateWeakPtrs(); | 320 factory.InvalidateWeakPtrs(); |
312 EXPECT_EQ(NULL, ptr2.get()); | 321 EXPECT_EQ(nullptr, ptr2.get()); |
313 EXPECT_FALSE(factory.HasWeakPtrs()); | 322 EXPECT_FALSE(factory.HasWeakPtrs()); |
314 } | 323 } |
315 | 324 |
316 TEST(WeakPtrTest, HasWeakPtrs) { | 325 TEST(WeakPtrTest, HasWeakPtrs) { |
317 int data; | 326 int data; |
318 WeakPtrFactory<int> factory(&data); | 327 WeakPtrFactory<int> factory(&data); |
319 { | 328 { |
320 WeakPtr<int> ptr = factory.GetWeakPtr(); | 329 WeakPtr<int> ptr = factory.GetWeakPtr(); |
321 EXPECT_TRUE(factory.HasWeakPtrs()); | 330 EXPECT_TRUE(factory.HasWeakPtrs()); |
322 } | 331 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 background.Start(); | 418 background.Start(); |
410 | 419 |
411 Arrow arrow; | 420 Arrow arrow; |
412 std::unique_ptr<TargetWithFactory> target(new TargetWithFactory); | 421 std::unique_ptr<TargetWithFactory> target(new TargetWithFactory); |
413 | 422 |
414 // Bind to main thread. | 423 // Bind to main thread. |
415 arrow.target = target->factory.GetWeakPtr(); | 424 arrow.target = target->factory.GetWeakPtr(); |
416 EXPECT_EQ(target.get(), arrow.target.get()); | 425 EXPECT_EQ(target.get(), arrow.target.get()); |
417 | 426 |
418 target->factory.InvalidateWeakPtrs(); | 427 target->factory.InvalidateWeakPtrs(); |
419 EXPECT_EQ(NULL, arrow.target.get()); | 428 EXPECT_EQ(nullptr, arrow.target.get()); |
420 | 429 |
421 arrow.target = target->factory.GetWeakPtr(); | 430 arrow.target = target->factory.GetWeakPtr(); |
422 // Re-bind to background thread. | 431 // Re-bind to background thread. |
423 EXPECT_EQ(target.get(), background.DeRef(&arrow)); | 432 EXPECT_EQ(target.get(), background.DeRef(&arrow)); |
424 | 433 |
425 // And the background thread can now delete the target. | 434 // And the background thread can now delete the target. |
426 background.DeleteTarget(target.release()); | 435 background.DeleteTarget(target.release()); |
427 } | 436 } |
428 | 437 |
429 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) { | 438 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 // - WeakPtr gets destroyed on Thread B | 481 // - WeakPtr gets destroyed on Thread B |
473 BackgroundThread background; | 482 BackgroundThread background; |
474 background.Start(); | 483 background.Start(); |
475 Arrow* arrow_copy; | 484 Arrow* arrow_copy; |
476 { | 485 { |
477 Target target; | 486 Target target; |
478 Arrow arrow; | 487 Arrow arrow; |
479 arrow.target = target.AsWeakPtr(); | 488 arrow.target = target.AsWeakPtr(); |
480 background.CreateArrowFromArrow(&arrow_copy, &arrow); | 489 background.CreateArrowFromArrow(&arrow_copy, &arrow); |
481 } | 490 } |
482 EXPECT_EQ(NULL, arrow_copy->target.get()); | 491 EXPECT_EQ(nullptr, arrow_copy->target.get()); |
483 background.DeleteArrow(arrow_copy); | 492 background.DeleteArrow(arrow_copy); |
484 } | 493 } |
485 | 494 |
486 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) { | 495 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) { |
487 // Main thread creates a Target object. | 496 // Main thread creates a Target object. |
488 Target target; | 497 Target target; |
489 // Main thread creates an arrow referencing the Target. | 498 // Main thread creates an arrow referencing the Target. |
490 Arrow *arrow = new Arrow(); | 499 Arrow *arrow = new Arrow(); |
491 arrow->target = target.AsWeakPtr(); | 500 arrow->target = target.AsWeakPtr(); |
492 | 501 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 background.Start(); | 642 background.Start(); |
634 background.DeleteTarget(target.release()); | 643 background.DeleteTarget(target.release()); |
635 | 644 |
636 // Main thread attempts to dereference the target, violating thread binding. | 645 // Main thread attempts to dereference the target, violating thread binding. |
637 ASSERT_DEATH(arrow.target.get(), ""); | 646 ASSERT_DEATH(arrow.target.get(), ""); |
638 } | 647 } |
639 | 648 |
640 #endif | 649 #endif |
641 | 650 |
642 } // namespace base | 651 } // namespace base |
OLD | NEW |