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 // Test that the factory can create new weak pointers after a 282 // InvalidateWeakPtrs call, and they remain valid until the next 283 // InvalidateWeakPtrs call. 284 WeakPtr<int> ptr2 = factory.GetWeakPtr(); 285 EXPECT_EQ(&data, ptr2.get()); 286 EXPECT_TRUE(factory.HasWeakPtrs()); 287 factory.InvalidateWeakPtrs(); 288 EXPECT_EQ(NULL, ptr2.get()); 289 EXPECT_FALSE(factory.HasWeakPtrs()); 290 } 291 292 TEST(WeakPtrTest, HasWeakPtrs) { 293 int data; 294 WeakPtrFactory<int> factory(&data); 295 { 296 WeakPtr<int> ptr = factory.GetWeakPtr(); 297 EXPECT_TRUE(factory.HasWeakPtrs()); 298 } 299 EXPECT_FALSE(factory.HasWeakPtrs()); 300 } 301 302 TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) { 303 // Test that it is OK to create an object that supports WeakPtr on one thread, 304 // but use it on another. This tests that we do not trip runtime checks that 305 // ensure that a WeakPtr is not used by multiple threads. 306 scoped_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject()); 307 WeakPtr<Target> weak_ptr = target->AsWeakPtr(); 308 EXPECT_EQ(target.get(), weak_ptr.get()); 309 } 310 311 TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) { 312 // Test that it is OK to create an object that has a WeakPtr member on one 313 // thread, but use it on another. This tests that we do not trip runtime 314 // checks that ensure that a WeakPtr is not used by multiple threads. 315 scoped_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject()); 316 Target target; 317 arrow->target = target.AsWeakPtr(); 318 EXPECT_EQ(&target, arrow->target.get()); 319 } 320 321 TEST(WeakPtrTest, MoveOwnershipImplicitly) { 322 // Move object ownership to another thread by releasing all weak pointers 323 // on the original thread first, and then establish WeakPtr on a different 324 // thread. 325 BackgroundThread background; 326 background.Start(); 327 328 Target* target = new Target(); 329 { 330 WeakPtr<Target> weak_ptr = target->AsWeakPtr(); 331 // Main thread deletes the WeakPtr, then the thread ownership of the 332 // object can be implicitly moved. 333 } 334 Arrow* arrow; 335 336 // Background thread creates WeakPtr(and implicitly owns the object). 337 background.CreateArrowFromTarget(&arrow, target); 338 EXPECT_EQ(background.DeRef(arrow), target); 339 340 { 341 // Main thread creates another WeakPtr, but this does not trigger implicitly 342 // thread ownership move. 343 Arrow arrow; 344 arrow.target = target->AsWeakPtr(); 345 346 // The new WeakPtr is owned by background thread. 347 EXPECT_EQ(target, background.DeRef(&arrow)); 348 } 349 350 // Target can only be deleted on background thread. 351 background.DeleteTarget(target); 352 background.DeleteArrow(arrow); 353 } 354 355 TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) { 356 BackgroundThread background; 357 background.Start(); 358 359 Arrow* arrow; 360 { 361 Target target; 362 // Background thread creates WeakPtr. 363 background.CreateArrowFromTarget(&arrow, &target); 364 365 // Bind to background thread. 366 EXPECT_EQ(&target, background.DeRef(arrow)); 367 368 // Release the only WeakPtr. 369 arrow->target.reset(); 370 371 // Now we should be able to create a new reference from this thread. 372 arrow->target = target.AsWeakPtr(); 373 374 // Re-bind to main thread. 375 EXPECT_EQ(&target, arrow->target.get()); 376 377 // And the main thread can now delete the target. 378 } 379 380 delete arrow; 381 } 382 383 TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) { 384 BackgroundThread background; 385 background.Start(); 386 387 Arrow arrow; 388 scoped_ptr<TargetWithFactory> target(new TargetWithFactory); 389 390 // Bind to main thread. 391 arrow.target = target->factory.GetWeakPtr(); 392 EXPECT_EQ(target.get(), arrow.target.get()); 393 394 target->factory.InvalidateWeakPtrs(); 395 EXPECT_EQ(NULL, arrow.target.get()); 396 397 arrow.target = target->factory.GetWeakPtr(); 398 // Re-bind to background thread. 399 EXPECT_EQ(target.get(), background.DeRef(&arrow)); 400 401 // And the background thread can now delete the target. 402 background.DeleteTarget(target.release()); 403 } 404 405 TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) { 406 // Originating thread has a WeakPtr that outlives others. 407 // - Main thread creates a WeakPtr 408 // - Background thread creates a WeakPtr copy from the one in main thread 409 // - Destruct the WeakPtr on background thread 410 // - Destruct the WeakPtr on main thread 411 BackgroundThread background; 412 background.Start(); 413 414 Target target; 415 Arrow arrow; 416 arrow.target = target.AsWeakPtr(); 417 418 Arrow* arrow_copy; 419 background.CreateArrowFromArrow(&arrow_copy, &arrow); 420 EXPECT_EQ(arrow_copy->target.get(), &target); 421 background.DeleteArrow(arrow_copy); 422 } 423 424 TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) { 425 // Originating thread drops all references before another thread. 426 // - Main thread creates a WeakPtr and passes copy to background thread 427 // - Destruct the pointer on main thread 428 // - Destruct the pointer on background thread 429 BackgroundThread background; 430 background.Start(); 431 432 Target target; 433 Arrow* arrow_copy; 434 { 435 Arrow arrow; 436 arrow.target = target.AsWeakPtr(); 437 background.CreateArrowFromArrow(&arrow_copy, &arrow); 438 } 439 EXPECT_EQ(arrow_copy->target.get(), &target); 440 background.DeleteArrow(arrow_copy); 441 } 442 443 TEST(WeakPtrTest, OwnerThreadDeletesObject) { 444 // Originating thread invalidates WeakPtrs while its held by other thread. 445 // - Main thread creates WeakPtr and passes Copy to background thread 446 // - Object gets destroyed on main thread 447 // (invalidates WeakPtr on background thread) 448 // - WeakPtr gets destroyed on Thread B 449 BackgroundThread background; 450 background.Start(); 451 Arrow* arrow_copy; 452 { 453 Target target; 454 Arrow arrow; 455 arrow.target = target.AsWeakPtr(); 456 background.CreateArrowFromArrow(&arrow_copy, &arrow); 457 } 458 EXPECT_EQ(NULL, arrow_copy->target.get()); 459 background.DeleteArrow(arrow_copy); 460 } 461 462 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) { 463 // Main thread creates a Target object. 464 Target target; 465 // Main thread creates an arrow referencing the Target. 466 Arrow *arrow = new Arrow(); 467 arrow->target = target.AsWeakPtr(); 468 469 // Background can copy and assign arrow (as well as the WeakPtr inside). 470 BackgroundThread background; 471 background.Start(); 472 background.CopyAndAssignArrow(arrow); 473 background.DeleteArrow(arrow); 474 } 475 476 TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) { 477 // Main thread creates a Target object. 478 Target target; 479 // Main thread creates an arrow referencing the Target. 480 Arrow *arrow = new Arrow(); 481 arrow->target = target.AsWeakPtr(); 482 483 // Background can copy and assign arrow's WeakPtr to a base class WeakPtr. 484 BackgroundThread background; 485 background.Start(); 486 background.CopyAndAssignArrowBase(arrow); 487 background.DeleteArrow(arrow); 488 } 489 490 TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) { 491 // Main thread creates a Target object. 492 Target target; 493 // Main thread creates an arrow referencing the Target. 494 Arrow* arrow = new Arrow(); 495 arrow->target = target.AsWeakPtr(); 496 497 // Background can delete arrow (as well as the WeakPtr inside). 498 BackgroundThread background; 499 background.Start(); 500 background.DeleteArrow(arrow); 501 } 502 503 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) && GTEST_HAS_DEATH_TEST 504 505 TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) { 506 // The default style "fast" does not support multi-threaded tests 507 // (introduces deadlock on Linux). 508 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 509 510 BackgroundThread background; 511 background.Start(); 512 513 // Main thread creates a Target object. 514 Target target; 515 // Main thread creates an arrow referencing the Target. 516 Arrow arrow; 517 arrow.target = target.AsWeakPtr(); 518 519 // Background copies the WeakPtr. 520 Arrow* arrow_copy; 521 background.CreateArrowFromArrow(&arrow_copy, &arrow); 522 523 // The copy is still bound to main thread so I can deref. 524 EXPECT_EQ(arrow.target.get(), arrow_copy->target.get()); 525 526 // Although background thread created the copy, it can not deref the copied 527 // WeakPtr. 528 ASSERT_DEATH(background.DeRef(arrow_copy), ""); 529 530 background.DeleteArrow(arrow_copy); 531 } 532 533 TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) { 534 // The default style "fast" does not support multi-threaded tests 535 // (introduces deadlock on Linux). 536 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 537 538 // Main thread creates a Target object. 539 Target target; 540 541 // Main thread creates an arrow referencing the Target (so target's 542 // thread ownership can not be implicitly moved). 543 Arrow arrow; 544 arrow.target = target.AsWeakPtr(); 545 arrow.target.get(); 546 547 // Background thread tries to deref target, which violates thread ownership. 548 BackgroundThread background; 549 background.Start(); 550 ASSERT_DEATH(background.DeRef(&arrow), ""); 551 } 552 553 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) { 554 // The default style "fast" does not support multi-threaded tests 555 // (introduces deadlock on Linux). 556 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 557 558 scoped_ptr<Target> target(new Target()); 559 560 // Main thread creates an arrow referencing the Target. 561 Arrow arrow; 562 arrow.target = target->AsWeakPtr(); 563 564 // Background thread tries to deref target, binding it to the thread. 565 BackgroundThread background; 566 background.Start(); 567 background.DeRef(&arrow); 568 569 // Main thread deletes Target, violating thread binding. 570 ASSERT_DEATH(target.reset(), ""); 571 572 // |target.reset()| died so |target| still holds the object, so we 573 // must pass it to the background thread to teardown. 574 background.DeleteTarget(target.release()); 575 } 576 577 TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) { 578 // The default style "fast" does not support multi-threaded tests 579 // (introduces deadlock on Linux). 580 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 581 582 scoped_ptr<Target> target(new Target()); 583 584 // Main thread creates an arrow referencing the Target, and references it, so 585 // that it becomes bound to the thread. 586 Arrow arrow; 587 arrow.target = target->AsWeakPtr(); 588 arrow.target.get(); 589 590 // Background thread tries to delete target, volating thread binding. 591 BackgroundThread background; 592 background.Start(); 593 ASSERT_DEATH(background.DeleteTarget(target.release()), ""); 594 } 595 596 TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) { 597 // The default style "fast" does not support multi-threaded tests 598 // (introduces deadlock on Linux). 599 ::testing::FLAGS_gtest_death_test_style = "threadsafe"; 600 601 scoped_ptr<Target> target(new Target()); 602 603 // Main thread creates an arrow referencing the Target. 604 Arrow arrow; 605 arrow.target = target->AsWeakPtr(); 606 607 // Background thread tries to delete target, binding the object to the thread. 608 BackgroundThread background; 609 background.Start(); 610 background.DeleteTarget(target.release()); 611 612 // Main thread attempts to dereference the target, violating thread binding. 613 ASSERT_DEATH(arrow.target.get(), ""); 614 } 615 616 #endif 617 618 } // namespace base 619