| 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 |