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 3 // found in the LICENSE file. 4 5 #include "base/memory/weak_ptr.h" 6 7 #include <string> 8 9 #include "base/bind.h" 10 #include "base/debug/leak_annotations.h" 11 #include "base/memory/scoped_ptr.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/synchronization/waitable_event.h" 14 #include "base/threading/thread.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 namespace base { 18 namespace { 19 20 template <class T> 21 class OffThreadObjectCreator { 22 public: 23 static T* NewObject() { 24 T* result; 25 { 26 Thread creator_thread("creator_thread"); 27 creator_thread.Start(); 28 creator_thread.message_loop()->PostTask( 29 FROM_HERE, 30 base::Bind(OffThreadObjectCreator::CreateObject, &result)); 31 } 32 DCHECK(result); // We synchronized on thread destruction above. 33 return result; 34 } 35 private: 36 static void CreateObject(T** result) { 37 *result = new T; 38 } 39 }; 40 41 struct Base { 42 std::string member; 43 }; 44 struct Derived : public Base {}; 45 46 struct TargetBase {}; 47 struct Target : public TargetBase, public SupportsWeakPtr<Target> { 48 virtual ~Target() {} 49 }; 50 struct DerivedTarget : public Target {}; 51 struct Arrow { 52 WeakPtr<Target> target; 53 }; 54 struct TargetWithFactory : public Target { 55 TargetWithFactory() : factory(this) {} 56 WeakPtrFactory<Target> factory; 57 }; 58 59 // Helper class to create and destroy weak pointer copies 60 // and delete objects on a background thread. 61 class BackgroundThread : public Thread { 62 public: 63 BackgroundThread() : Thread("owner_thread") {} 64 65 virtual ~BackgroundThread() { 66 Stop(); 67 } 68 69 void CreateArrowFromTarget(Arrow** arrow, Target* target) { 70 WaitableEvent completion(true, false); 71 message_loop()->PostTask( 72 FROM_HERE, 73 base::Bind(&BackgroundThread::DoCreateArrowFromTarget, 74 arrow, target, &completion)); 75 completion.Wait(); 76 } 77 78 void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) { 79 WaitableEvent completion(true, false); 80 message_loop()->PostTask( 81 FROM_HERE, 82 base::Bind(&BackgroundThread::DoCreateArrowFromArrow, 83 arrow, other, &completion)); 84 completion.Wait(); 85 } 86 87 void DeleteTarget(Target* object) { 88 WaitableEvent completion(true, false); 89 message_loop()->PostTask( 90 FROM_HERE, 91 base::Bind(&BackgroundThread::DoDeleteTarget, object, &completion)); 92 completion.Wait(); 93 } 94 95 void CopyAndAssignArrow(Arrow* object) { 96 WaitableEvent completion(true, false); 97 message_loop()->PostTask( 98 FROM_HERE, 99 base::Bind(&BackgroundThread::DoCopyAndAssignArrow, 100 object, &completion)); 101 completion.Wait(); 102 } 103 104 void CopyAndAssignArrowBase(Arrow* object) { 105 WaitableEvent completion(true, false); 106 message_loop()->PostTask( 107 FROM_HERE, 108 base::Bind(&BackgroundThread::DoCopyAndAssignArrowBase, 109 object, &completion)); 110 completion.Wait(); 111 } 112 113 void DeleteArrow(Arrow* object) { 114 WaitableEvent completion(true, false); 115 message_loop()->PostTask( 116 FROM_HERE, 117 base::Bind(&BackgroundThread::DoDeleteArrow, object, &completion)); 118 completion.Wait(); 119 } 120 121 Target* DeRef(const Arrow* arrow) { 122 WaitableEvent completion(true, false); 123 Target* result = NULL; 124 message_loop()->PostTask( 125 FROM_HERE, 126 base::Bind(&BackgroundThread::DoDeRef, arrow, &result, &completion)); 127 completion.Wait(); 128 return result; 129 } 130 131 protected: 132 static void DoCreateArrowFromArrow(Arrow** arrow, 133 const Arrow* other, 134 WaitableEvent* completion) { 135 *arrow = new Arrow; 136 **arrow = *other; 137 completion->Signal(); 138 } 139 140 static void DoCreateArrowFromTarget(Arrow** arrow, 141 Target* target, 142 WaitableEvent* completion) { 143 *arrow = new Arrow; 144 (*arrow)->target = target->AsWeakPtr(); 145 completion->Signal(); 146 } 147 148 static void DoDeRef(const Arrow* arrow, 149 Target** result, 150 WaitableEvent* completion) { 151 *result = arrow->target.get(); 152 completion->Signal(); 153 } 154 155 static void DoDeleteTarget(Target* object, WaitableEvent* completion) { 156 delete object; 157 completion->Signal(); 158 } 159 160 static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) { 161 // Copy constructor. 162 Arrow a = *object; 163 // Assignment operator. 164 *object = a; 165 completion->Signal(); 166 } 167 168 static void DoCopyAndAssignArrowBase( 169 Arrow* object, 170 WaitableEvent* completion) { 171 // Copy constructor. 172 WeakPtr<TargetBase> b = object->target; 173 // Assignment operator. 174 WeakPtr<TargetBase> c; 175 c = object->target; 176 completion->Signal(); 177 } 178 179 static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) { 180 delete object; 181 completion->Signal(); 182 } 183 }; 184 185 } // namespace 186 187 TEST(WeakPtrFactoryTest, Basic) { 188 int data; 189 WeakPtrFactory<int> factory(&data); 190 WeakPtr<int> ptr = factory.GetWeakPtr(); 191 EXPECT_EQ(&data, ptr.get()); 192 } 193 194 TEST(WeakPtrFactoryTest, Comparison) { 195 int data; 196 WeakPtrFactory<int> factory(&data); 197 WeakPtr<int> ptr = factory.GetWeakPtr(); 198 WeakPtr<int> ptr2 = ptr; 199 EXPECT_EQ(ptr.get(), ptr2.get()); 200 } 201 202 TEST(WeakPtrFactoryTest, OutOfScope) { 203 WeakPtr<int> ptr; 204 EXPECT_EQ(NULL, ptr.get()); 205 { 206 int data; 207 WeakPtrFactory<int> factory(&data); 208 ptr = factory.GetWeakPtr(); 209 } 210 EXPECT_EQ(NULL, ptr.get()); 211 } 212 213 TEST(WeakPtrFactoryTest, Multiple) { 214 WeakPtr<int> a, b; 215 { 216 int data; 217 WeakPtrFactory<int> factory(&data); 218 a = factory.GetWeakPtr(); 219 b = factory.GetWeakPtr(); 220 EXPECT_EQ(&data, a.get()); 221 EXPECT_EQ(&data, b.get()); 222 } 223 EXPECT_EQ(NULL, a.get()); 224 EXPECT_EQ(NULL, b.get()); 225 } 226 227 TEST(WeakPtrFactoryTest, MultipleStaged) { 228 WeakPtr<int> a; 229 { 230 int data; 231 WeakPtrFactory<int> factory(&data); 232 a = factory.GetWeakPtr(); 233 { 234 WeakPtr<int> b = factory.GetWeakPtr(); 235 } 236 EXPECT_TRUE(NULL != a.get()); 237 } 238 EXPECT_EQ(NULL, a.get()); 239 } 240 241 TEST(WeakPtrFactoryTest, Dereference) { 242 Base data; 243 data.member = "123456"; 244 WeakPtrFactory<Base> factory(&data); 245 WeakPtr<Base> ptr = factory.GetWeakPtr(); 246 EXPECT_EQ(&data, ptr.get()); 247 EXPECT_EQ(data.member, (*ptr).member); 248 EXPECT_EQ(data.member, ptr->member); 249 } 250 251 TEST(WeakPtrFactoryTest, UpCast) { 252 Derived data; 253 WeakPtrFactory<Derived> factory(&data); 254 WeakPtr<Base> ptr = factory.GetWeakPtr(); 255 ptr = factory.GetWeakPtr(); 256 EXPECT_EQ(ptr.get(), &data); 257 } 258 259 TEST(WeakPtrTest, SupportsWeakPtr) { 260 Target target; 261 WeakPtr<Target> ptr = target.AsWeakPtr(); 262 EXPECT_EQ(&target, ptr.get()); 263 } 264 265 TEST(WeakPtrTest, DerivedTarget) { 266 DerivedTarget target; 267 WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target); 268 EXPECT_EQ(&target, ptr.get()); 269 } 270 271 TEST(WeakPtrTest, InvalidateWeakPtrs) { 272 int data; 273 WeakPtrFactory<int> factory(&data); 274 WeakPtr<int> ptr = factory.GetWeakPtr(); 275 EXPECT_EQ(&data, ptr.get()); 276 EXPECT_TRUE(factory.HasWeakPtrs()); 277 factory.InvalidateWeakPtrs(); 278 EXPECT_EQ(NULL, ptr.get()); 279 EXPECT_FALSE(factory.HasWeakPtrs()); 280 } 281 282 TEST(WeakPtrTest, HasWeakPtrs) { 283 int data; 284 WeakPtrFactory<int> factory(&data); 285 { 286 WeakPtr<int> ptr = factory.GetWeakPtr(); 287 EXPECT_TRUE(factory.HasWeakPtrs()); 288 } 289 EXPECT_FALSE(factory.HasWeakPtrs()); 290 } 291 292 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) { 293 // Test that it is OK to create an object that supports WeakPtr on one thread, 294 // but use it on another. This tests that we do not trip runtime checks that 295 // ensure that a WeakPtr is not used by multiple threads. 296 scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject()); 297 WeakPtr<Target> weak_ptr = target->AsWeakPtr(); 298 EXPECT_EQ(target.get(), weak_ptr.get()); 299 } 300 301 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) { 302 // Test that it is OK to create an object that has a WeakPtr member on one 303 // thread, but use it on another. This tests that we do not trip runtime 304 // checks that ensure that a WeakPtr is not used by multiple threads. 305 scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject()); 306 Target target; 307 arrow->target = target.AsWeakPtr(); 308 EXPECT_EQ(&target, arrow->target.get()); 309 } 310 311 TEST(WeakPtrTest, MoveOwnershipImplicitly) { 312 // Move object ownership to another thread by releasing all weak pointers 313 // on the original thread first, and then establish WeakPtr on a different 314 // thread. 315 BackgroundThread background; 316 background.Start(); 317 318 Target* target = new Target(); 319 { 320 WeakPtr<Target> weak_ptr = target->AsWeakPtr(); 321 // Main thread deletes the WeakPtr, then the thread ownership of the 322 // object can be implicitly moved. 323 } 324 Arrow* arrow; 325 326 // Background thread creates WeakPtr(and implicitly owns the object). 327 background.CreateArrowFromTarget(&arrow, target); 328 EXPECT_EQ(background.DeRef(arrow), target); 329 330 { 331 // Main thread creates another WeakPtr, but this does not trigger implicitly 332 // thread ownership move. 333 Arrow arrow; 334 arrow.target = target->AsWeakPtr(); 335 336 // The new WeakPtr is owned by background thread. 337 EXPECT_EQ(target, background.DeRef(&arrow)); 338 } 339 340 // Target can only be deleted on background thread. 341 background.DeleteTarget(target); 342 background.DeleteArrow(arrow); 343 } 344 345 TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) { 346 BackgroundThread background; 347 background.Start(); 348 349 Arrow* arrow; 350 { 351 Target target; 352 // Background thread creates WeakPtr. 353 background.CreateArrowFromTarget(&arrow, &target); 354 355 // Bind to background thread. 356 EXPECT_EQ(&target, background.DeRef(arrow)); 357 358 // Release the only WeakPtr. 359 arrow->target.reset(); 360 361 // Now we should be able to create a new reference from this thread. 362 arrow->target = target.AsWeakPtr(); 363 364 // Re-bind to main thread. 365 EXPECT_EQ(&target, arrow->target.get()); 366 367 // And the main thread can now delete the target. 368 } 369 370 delete arrow; 371 } 372 373 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) { 374 BackgroundThread background; 375 background.Start(); 376 377 Arrow arrow; 378 scoped_ptr<TargetWithFactory> target(new TargetWithFactory); 379 380 // Bind to main thread. 381 arrow.target = target->factory.GetWeakPtr(); 382 EXPECT_EQ(target.get(), arrow.target.get()); 383 384 target->factory.InvalidateWeakPtrs(); 385 EXPECT_EQ(NULL, arrow.target.get()); 386 387 arrow.target = target->factory.GetWeakPtr(); 388 // Re-bind to background thread. 389 EXPECT_EQ(target.get(), background.DeRef(&arrow)); 390 391 // And the background thread can now delete the target. 392 background.DeleteTarget(target.release()); 393 } 394 395 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) { 396 // Originating thread has a WeakPtr that outlives others. 397 // - Main thread creates a WeakPtr 398 // - Background thread creates a WeakPtr copy from the one in main thread 399 // - Destruct the WeakPtr on background thread 400 // - Destruct the WeakPtr on main thread 401 BackgroundThread background; 402 background.Start(); 403 404 Target target; 405 Arrow arrow; 406 arrow.target = target.AsWeakPtr(); 407 408 Arrow* arrow_copy; 409 background.CreateArrowFromArrow(&arrow_copy, &arrow); 410 EXPECT_EQ(arrow_copy->target.get(), &target); 411 background.DeleteArrow(arrow_copy); 412 } 413 414 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) { 415 // Originating thread drops all references before another thread. 416 // - Main thread creates a WeakPtr and passes copy to background thread 417 // - Destruct the pointer on main thread 418 // - Destruct the pointer on background thread 419 BackgroundThread background; 420 background.Start(); 421 422 Target target; 423 Arrow* arrow_copy; 424 { 425 Arrow arrow; 426 arrow.target = target.AsWeakPtr(); 427 background.CreateArrowFromArrow(&arrow_copy, &arrow); 428 } 429 EXPECT_EQ(arrow_copy->target.get(), &target); 430 background.DeleteArrow(arrow_copy); 431 } 432 433 TEST(WeakPtrTest, OwnerThreadDeletesObject) { 434 // Originating thread invalidates WeakPtrs while its held by other thread. 435 // - Main thread creates WeakPtr and passes Copy to background thread 436 // - Object gets destroyed on main thread 437 // (invalidates WeakPtr on background thread) 438 // - WeakPtr gets destroyed on Thread B 439 BackgroundThread background; 440 background.Start(); 441 Arrow* arrow_copy; 442 { 443 Target target; 444 Arrow arrow; 445 arrow.target = target.AsWeakPtr(); 446 background.CreateArrowFromArrow(&arrow_copy, &arrow); 447 } 448 EXPECT_EQ(NULL, arrow_copy->target.get()); 449 background.DeleteArrow(arrow_copy); 450 } 451 452 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) { 453 // Main thread creates a Target object. 454 Target target; 455 // Main thread creates an arrow referencing the Target. 456 Arrow *arrow = new Arrow(); 457 arrow->target = target.AsWeakPtr(); 458 459 // Background can copy and assign arrow (as well as the WeakPtr inside). 460 BackgroundThread background; 461 background.Start(); 462 background.CopyAndAssignArrow(arrow); 463 background.DeleteArrow(arrow); 464 } 465 466 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) { 467 // Main thread creates a Target object. 468 Target target; 469 // Main thread creates an arrow referencing the Target. 470 Arrow *arrow = new Arrow(); 471 arrow->target = target.AsWeakPtr(); 472 473 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr. 474 BackgroundThread background; 475 background.Start(); 476 background.CopyAndAssignArrowBase(arrow); 477 background.DeleteArrow(arrow); 478 } 479 480 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) { 481 // Main thread creates a Target object. 482 Target target; 483 // Main thread creates an arrow referencing the Target. 484 Arrow* arrow = new Arrow(); 485 arrow->target = target.AsWeakPtr(); 486 487 // Background can delete arrow (as well as the WeakPtr inside). 488 BackgroundThread background; 489 background.Start(); 490 background.DeleteArrow(arrow); 491 } 492 493 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST 494 495 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) { 496 // The default style "fast" does not support multi-threaded tests 497 // (introduces deadlock on Linux). 498 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 499 500 BackgroundThread background; 501 background.Start(); 502 503 // Main thread creates a Target object. 504 Target target; 505 // Main thread creates an arrow referencing the Target. 506 Arrow arrow; 507 arrow.target = target.AsWeakPtr(); 508 509 // Background copies the WeakPtr. 510 Arrow* arrow_copy; 511 background.CreateArrowFromArrow(&arrow_copy, &arrow); 512 513 // The copy is still bound to main thread so I can deref. 514 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get()); 515 516 // Although background thread created the copy, it can not deref the copied 517 // WeakPtr. 518 ASSERT_DEATH(background.DeRef(arrow_copy), ""); 519 520 background.DeleteArrow(arrow_copy); 521 } 522 523 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) { 524 // The default style "fast" does not support multi-threaded tests 525 // (introduces deadlock on Linux). 526 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 527 528 // Main thread creates a Target object. 529 Target target; 530 531 // Main thread creates an arrow referencing the Target (so target's 532 // thread ownership can not be implicitly moved). 533 Arrow arrow; 534 arrow.target = target.AsWeakPtr(); 535 arrow.target.get(); 536 537 // Background thread tries to deref target, which violates thread ownership. 538 BackgroundThread background; 539 background.Start(); 540 ASSERT_DEATH(background.DeRef(&arrow), ""); 541 } 542 543 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) { 544 // The default style "fast" does not support multi-threaded tests 545 // (introduces deadlock on Linux). 546 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 547 548 scoped_ptr<Target> target(new Target()); 549 550 // Main thread creates an arrow referencing the Target. 551 Arrow arrow; 552 arrow.target = target->AsWeakPtr(); 553 554 // Background thread tries to deref target, binding it to the thread. 555 BackgroundThread background; 556 background.Start(); 557 background.DeRef(&arrow); 558 559 // Main thread deletes Target, violating thread binding. 560 ASSERT_DEATH(target.reset(), ""); 561 562 // |target.reset()| died so |target| still holds the object, so we 563 // must pass it to the background thread to teardown. 564 background.DeleteTarget(target.release()); 565 } 566 567 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) { 568 // The default style "fast" does not support multi-threaded tests 569 // (introduces deadlock on Linux). 570 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 571 572 scoped_ptr<Target> target(new Target()); 573 574 // Main thread creates an arrow referencing the Target, and references it, so 575 // that it becomes bound to the thread. 576 Arrow arrow; 577 arrow.target = target->AsWeakPtr(); 578 arrow.target.get(); 579 580 // Background thread tries to delete target, volating thread binding. 581 BackgroundThread background; 582 background.Start(); 583 ASSERT_DEATH(background.DeleteTarget(target.release()), ""); 584 } 585 586 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) { 587 // The default style "fast" does not support multi-threaded tests 588 // (introduces deadlock on Linux). 589 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 590 591 scoped_ptr<Target> target(new Target()); 592 593 // Main thread creates an arrow referencing the Target. 594 Arrow arrow; 595 arrow.target = target->AsWeakPtr(); 596 597 // Background thread tries to delete target, binding the object to the thread. 598 BackgroundThread background; 599 background.Start(); 600 background.DeleteTarget(target.release()); 601 602 // Main thread attempts to dereference the target, violating thread binding. 603 ASSERT_DEATH(arrow.target.get(), ""); 604 } 605 606 #endif 607 608 } // namespace base 609