1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_RefPtr_h 8 #define mozilla_RefPtr_h 9 10 #include "mozilla/AlreadyAddRefed.h" 11 #include "mozilla/Assertions.h" 12 #include "mozilla/Attributes.h" 13 14 /*****************************************************************************/ 15 16 // template <class T> class RefPtrGetterAddRefs; 17 18 class nsCOMPtr_helper; 19 20 namespace mozilla { 21 template<class T> class OwningNonNull; 22 } // namespace mozilla 23 24 template <class T> 25 class RefPtr 26 { 27 private: 28 void assign_with_AddRef(T * aRawPtr)29 assign_with_AddRef(T* aRawPtr) 30 { 31 if (aRawPtr) { 32 AddRefTraits<T>::AddRef(aRawPtr); 33 } 34 assign_assuming_AddRef(aRawPtr); 35 } 36 37 void assign_assuming_AddRef(T * aNewPtr)38 assign_assuming_AddRef(T* aNewPtr) 39 { 40 T* oldPtr = mRawPtr; 41 mRawPtr = aNewPtr; 42 if (oldPtr) { 43 AddRefTraits<T>::Release(oldPtr); 44 } 45 } 46 47 private: 48 T* MOZ_OWNING_REF mRawPtr; 49 50 public: 51 typedef T element_type; 52 ~RefPtr()53 ~RefPtr() 54 { 55 if (mRawPtr) { 56 AddRefTraits<T>::Release(mRawPtr); 57 } 58 } 59 60 // Constructors 61 RefPtr()62 RefPtr() 63 : mRawPtr(0) 64 // default constructor 65 { 66 } 67 RefPtr(const RefPtr<T> & aSmartPtr)68 RefPtr(const RefPtr<T>& aSmartPtr) 69 : mRawPtr(aSmartPtr.mRawPtr) 70 // copy-constructor 71 { 72 if (mRawPtr) { 73 AddRefTraits<T>::AddRef(mRawPtr); 74 } 75 } 76 RefPtr(RefPtr<T> && aRefPtr)77 RefPtr(RefPtr<T>&& aRefPtr) 78 : mRawPtr(aRefPtr.mRawPtr) 79 { 80 aRefPtr.mRawPtr = nullptr; 81 } 82 83 // construct from a raw pointer (of the right type) 84 RefPtr(T * aRawPtr)85 MOZ_IMPLICIT RefPtr(T* aRawPtr) 86 : mRawPtr(aRawPtr) 87 { 88 if (mRawPtr) { 89 AddRefTraits<T>::AddRef(mRawPtr); 90 } 91 } 92 93 template <typename I> RefPtr(already_AddRefed<I> & aSmartPtr)94 MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr) 95 : mRawPtr(aSmartPtr.take()) 96 // construct from |already_AddRefed| 97 { 98 } 99 100 template <typename I> RefPtr(already_AddRefed<I> && aSmartPtr)101 MOZ_IMPLICIT RefPtr(already_AddRefed<I>&& aSmartPtr) 102 : mRawPtr(aSmartPtr.take()) 103 // construct from |otherRefPtr.forget()| 104 { 105 } 106 107 template <typename I> RefPtr(const RefPtr<I> & aSmartPtr)108 MOZ_IMPLICIT RefPtr(const RefPtr<I>& aSmartPtr) 109 : mRawPtr(aSmartPtr.get()) 110 // copy-construct from a smart pointer with a related pointer type 111 { 112 if (mRawPtr) { 113 AddRefTraits<T>::AddRef(mRawPtr); 114 } 115 } 116 117 template <typename I> RefPtr(RefPtr<I> && aSmartPtr)118 MOZ_IMPLICIT RefPtr(RefPtr<I>&& aSmartPtr) 119 : mRawPtr(aSmartPtr.forget().take()) 120 // construct from |Move(RefPtr<SomeSubclassOfT>)|. 121 { 122 } 123 124 MOZ_IMPLICIT RefPtr(const nsCOMPtr_helper& aHelper); 125 126 // Defined in OwningNonNull.h 127 template<class U> 128 MOZ_IMPLICIT RefPtr(const mozilla::OwningNonNull<U>& aOther); 129 130 // Assignment operators 131 132 RefPtr<T>& 133 operator=(const RefPtr<T>& aRhs) 134 // copy assignment operator 135 { 136 assign_with_AddRef(aRhs.mRawPtr); 137 return *this; 138 } 139 140 template <typename I> 141 RefPtr<T>& 142 operator=(const RefPtr<I>& aRhs) 143 // assign from an RefPtr of a related pointer type 144 { 145 assign_with_AddRef(aRhs.get()); 146 return *this; 147 } 148 149 RefPtr<T>& 150 operator=(T* aRhs) 151 // assign from a raw pointer (of the right type) 152 { 153 assign_with_AddRef(aRhs); 154 return *this; 155 } 156 157 template <typename I> 158 RefPtr<T>& 159 operator=(already_AddRefed<I>& aRhs) 160 // assign from |already_AddRefed| 161 { 162 assign_assuming_AddRef(aRhs.take()); 163 return *this; 164 } 165 166 template <typename I> 167 RefPtr<T>& 168 operator=(already_AddRefed<I> && aRhs) 169 // assign from |otherRefPtr.forget()| 170 { 171 assign_assuming_AddRef(aRhs.take()); 172 return *this; 173 } 174 175 RefPtr<T>& operator=(const nsCOMPtr_helper& aHelper); 176 177 RefPtr<T>& 178 operator=(RefPtr<T> && aRefPtr) 179 { 180 assign_assuming_AddRef(aRefPtr.mRawPtr); 181 aRefPtr.mRawPtr = nullptr; 182 return *this; 183 } 184 185 // Defined in OwningNonNull.h 186 template<class U> 187 RefPtr<T>& 188 operator=(const mozilla::OwningNonNull<U>& aOther); 189 190 // Other pointer operators 191 192 void swap(RefPtr<T> & aRhs)193 swap(RefPtr<T>& aRhs) 194 // ...exchange ownership with |aRhs|; can save a pair of refcount operations 195 { 196 T* temp = aRhs.mRawPtr; 197 aRhs.mRawPtr = mRawPtr; 198 mRawPtr = temp; 199 } 200 201 void swap(T * & aRhs)202 swap(T*& aRhs) 203 // ...exchange ownership with |aRhs|; can save a pair of refcount operations 204 { 205 T* temp = aRhs; 206 aRhs = mRawPtr; 207 mRawPtr = temp; 208 } 209 210 already_AddRefed<T> forget()211 forget() 212 // return the value of mRawPtr and null out mRawPtr. Useful for 213 // already_AddRefed return values. 214 { 215 T* temp = 0; 216 swap(temp); 217 return already_AddRefed<T>(temp); 218 } 219 220 template <typename I> 221 void forget(I ** aRhs)222 forget(I** aRhs) 223 // Set the target of aRhs to the value of mRawPtr and null out mRawPtr. 224 // Useful to avoid unnecessary AddRef/Release pairs with "out" 225 // parameters where aRhs bay be a T** or an I** where I is a base class 226 // of T. 227 { 228 MOZ_ASSERT(aRhs, "Null pointer passed to forget!"); 229 *aRhs = mRawPtr; 230 mRawPtr = 0; 231 } 232 233 T* get()234 get() const 235 /* 236 Prefer the implicit conversion provided automatically by |operator T*() const|. 237 Use |get()| to resolve ambiguity or to get a castable pointer. 238 */ 239 { 240 return const_cast<T*>(mRawPtr); 241 } 242 243 operator T*() const 244 #ifdef MOZ_HAVE_REF_QUALIFIERS 245 & 246 #endif 247 /* 248 ...makes an |RefPtr| act like its underlying raw pointer type whenever it 249 is used in a context where a raw pointer is expected. It is this operator 250 that makes an |RefPtr| substitutable for a raw pointer. 251 252 Prefer the implicit use of this operator to calling |get()|, except where 253 necessary to resolve ambiguity. 254 */ 255 { 256 return get(); 257 } 258 259 #ifdef MOZ_HAVE_REF_QUALIFIERS 260 // Don't allow implicit conversion of temporary RefPtr to raw pointer, 261 // because the refcount might be one and the pointer will immediately become 262 // invalid. 263 operator T*() const && = delete; 264 265 // These are needed to avoid the deleted operator above. XXX Why is operator! 266 // needed separately? Shouldn't the compiler prefer using the non-deleted 267 // operator bool instead of the deleted operator T*? 268 explicit operator bool() const { return !!mRawPtr; } 269 bool operator!() const { return !mRawPtr; } 270 #endif 271 272 T* 273 operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN 274 { 275 MOZ_ASSERT(mRawPtr != 0, 276 "You can't dereference a NULL RefPtr with operator->()."); 277 return get(); 278 } 279 280 template <typename R, typename... Args> 281 class Proxy 282 { 283 typedef R (T::*member_function)(Args...); 284 T* mRawPtr; 285 member_function mFunction; 286 public: Proxy(T * aRawPtr,member_function aFunction)287 Proxy(T* aRawPtr, member_function aFunction) 288 : mRawPtr(aRawPtr), 289 mFunction(aFunction) 290 { 291 } 292 template<typename... ActualArgs> operator()293 R operator()(ActualArgs&&... aArgs) 294 { 295 return ((*mRawPtr).*mFunction)(mozilla::Forward<ActualArgs>(aArgs)...); 296 } 297 }; 298 299 template <typename R, typename... Args> 300 Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const 301 { 302 MOZ_ASSERT(mRawPtr != 0, 303 "You can't dereference a NULL RefPtr with operator->*()."); 304 return Proxy<R, Args...>(get(), aFptr); 305 } 306 307 RefPtr<T>* get_address()308 get_address() 309 // This is not intended to be used by clients. See |address_of| 310 // below. 311 { 312 return this; 313 } 314 315 const RefPtr<T>* get_address()316 get_address() const 317 // This is not intended to be used by clients. See |address_of| 318 // below. 319 { 320 return this; 321 } 322 323 public: 324 T& 325 operator*() const 326 { 327 MOZ_ASSERT(mRawPtr != 0, 328 "You can't dereference a NULL RefPtr with operator*()."); 329 return *get(); 330 } 331 332 T** StartAssignment()333 StartAssignment() 334 { 335 assign_assuming_AddRef(0); 336 return reinterpret_cast<T**>(&mRawPtr); 337 } 338 private: 339 // This helper class makes |RefPtr<const T>| possible by casting away 340 // the constness from the pointer when calling AddRef() and Release(). 341 // 342 // This is necessary because AddRef() and Release() implementations can't 343 // generally expected to be const themselves (without heavy use of |mutable| 344 // and |const_cast| in their own implementations). 345 // 346 // This should be sound because while |RefPtr<const T>| provides a 347 // const view of an object, the object itself should not be const (it 348 // would have to be allocated as |new const T| or similar to be const). 349 350 // Because some classes make their AddRef/Release implementations private 351 // and then friend RefPtr to make them visible, we redirect AddRefTraits's 352 // calls to static helper functions in RefPtr so we don't have to figure 353 // out how to make AddRefTraits visible to *those* classes. 354 static MOZ_ALWAYS_INLINE void AddRefTraitsAddRefHelper(typename mozilla::RemoveConst<T>::Type * aPtr)355 AddRefTraitsAddRefHelper(typename mozilla::RemoveConst<T>::Type* aPtr) 356 { 357 aPtr->AddRef(); 358 } 359 static MOZ_ALWAYS_INLINE void AddRefTraitsReleaseHelper(typename mozilla::RemoveConst<T>::Type * aPtr)360 AddRefTraitsReleaseHelper(typename mozilla::RemoveConst<T>::Type* aPtr) 361 { 362 aPtr->Release(); 363 } 364 365 template<class U> 366 struct AddRefTraits 367 { AddRefAddRefTraits368 static void AddRef(U* aPtr) { 369 RefPtr<T>::AddRefTraitsAddRefHelper(aPtr); 370 } ReleaseAddRefTraits371 static void Release(U* aPtr) { 372 RefPtr<T>::AddRefTraitsReleaseHelper(aPtr); 373 } 374 }; 375 template<class U> 376 struct AddRefTraits<const U> 377 { 378 static void AddRef(const U* aPtr) { 379 RefPtr<T>::AddRefTraitsAddRefHelper(const_cast<U*>(aPtr)); 380 } 381 static void Release(const U* aPtr) { 382 RefPtr<T>::AddRefTraitsReleaseHelper(const_cast<U*>(aPtr)); 383 } 384 }; 385 }; 386 387 class nsCycleCollectionTraversalCallback; 388 template <typename T> 389 void 390 CycleCollectionNoteChild(nsCycleCollectionTraversalCallback& aCallback, 391 T* aChild, const char* aName, uint32_t aFlags); 392 393 template <typename T> 394 inline void 395 ImplCycleCollectionUnlink(RefPtr<T>& aField) 396 { 397 aField = nullptr; 398 } 399 400 template <typename T> 401 inline void 402 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, 403 RefPtr<T>& aField, 404 const char* aName, 405 uint32_t aFlags = 0) 406 { 407 CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags); 408 } 409 410 template <class T> 411 inline RefPtr<T>* 412 address_of(RefPtr<T>& aPtr) 413 { 414 return aPtr.get_address(); 415 } 416 417 template <class T> 418 inline const RefPtr<T>* 419 address_of(const RefPtr<T>& aPtr) 420 { 421 return aPtr.get_address(); 422 } 423 424 template <class T> 425 class RefPtrGetterAddRefs 426 /* 427 ... 428 429 This class is designed to be used for anonymous temporary objects in the 430 argument list of calls that return COM interface pointers, e.g., 431 432 RefPtr<IFoo> fooP; 433 ...->GetAddRefedPointer(getter_AddRefs(fooP)) 434 435 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead. 436 437 When initialized with a |RefPtr|, as in the example above, it returns 438 a |void**|, a |T**|, or an |nsISupports**| as needed, that the 439 outer call (|GetAddRefedPointer| in this case) can fill in. 440 441 This type should be a nested class inside |RefPtr<T>|. 442 */ 443 { 444 public: 445 explicit 446 RefPtrGetterAddRefs(RefPtr<T>& aSmartPtr) 447 : mTargetSmartPtr(aSmartPtr) 448 { 449 // nothing else to do 450 } 451 452 operator void**() 453 { 454 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment()); 455 } 456 457 operator T**() 458 { 459 return mTargetSmartPtr.StartAssignment(); 460 } 461 462 T*& 463 operator*() 464 { 465 return *(mTargetSmartPtr.StartAssignment()); 466 } 467 468 private: 469 RefPtr<T>& mTargetSmartPtr; 470 }; 471 472 template <class T> 473 inline RefPtrGetterAddRefs<T> 474 getter_AddRefs(RefPtr<T>& aSmartPtr) 475 /* 476 Used around a |RefPtr| when 477 ...makes the class |RefPtrGetterAddRefs<T>| invisible. 478 */ 479 { 480 return RefPtrGetterAddRefs<T>(aSmartPtr); 481 } 482 483 484 // Comparing two |RefPtr|s 485 486 template <class T, class U> 487 inline bool 488 operator==(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs) 489 { 490 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get()); 491 } 492 493 494 template <class T, class U> 495 inline bool 496 operator!=(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs) 497 { 498 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get()); 499 } 500 501 502 // Comparing an |RefPtr| to a raw pointer 503 504 template <class T, class U> 505 inline bool 506 operator==(const RefPtr<T>& aLhs, const U* aRhs) 507 { 508 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs); 509 } 510 511 template <class T, class U> 512 inline bool 513 operator==(const U* aLhs, const RefPtr<T>& aRhs) 514 { 515 return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get()); 516 } 517 518 template <class T, class U> 519 inline bool 520 operator!=(const RefPtr<T>& aLhs, const U* aRhs) 521 { 522 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs); 523 } 524 525 template <class T, class U> 526 inline bool 527 operator!=(const U* aLhs, const RefPtr<T>& aRhs) 528 { 529 return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get()); 530 } 531 532 template <class T, class U> 533 inline bool 534 operator==(const RefPtr<T>& aLhs, U* aRhs) 535 { 536 return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs); 537 } 538 539 template <class T, class U> 540 inline bool 541 operator==(U* aLhs, const RefPtr<T>& aRhs) 542 { 543 return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get()); 544 } 545 546 template <class T, class U> 547 inline bool 548 operator!=(const RefPtr<T>& aLhs, U* aRhs) 549 { 550 return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs); 551 } 552 553 template <class T, class U> 554 inline bool 555 operator!=(U* aLhs, const RefPtr<T>& aRhs) 556 { 557 return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get()); 558 } 559 560 // Comparing an |RefPtr| to |nullptr| 561 562 template <class T> 563 inline bool 564 operator==(const RefPtr<T>& aLhs, decltype(nullptr)) 565 { 566 return aLhs.get() == nullptr; 567 } 568 569 template <class T> 570 inline bool 571 operator==(decltype(nullptr), const RefPtr<T>& aRhs) 572 { 573 return nullptr == aRhs.get(); 574 } 575 576 template <class T> 577 inline bool 578 operator!=(const RefPtr<T>& aLhs, decltype(nullptr)) 579 { 580 return aLhs.get() != nullptr; 581 } 582 583 template <class T> 584 inline bool 585 operator!=(decltype(nullptr), const RefPtr<T>& aRhs) 586 { 587 return nullptr != aRhs.get(); 588 } 589 590 /*****************************************************************************/ 591 592 template <class T> 593 inline already_AddRefed<T> 594 do_AddRef(T*&& aObj) 595 { 596 RefPtr<T> ref(aObj); 597 return ref.forget(); 598 } 599 600 namespace mozilla { 601 602 /** 603 * Helper function to be able to conveniently write things like: 604 * 605 * already_AddRefed<T> 606 * f(...) 607 * { 608 * return MakeAndAddRef<T>(...); 609 * } 610 */ 611 template<typename T, typename... Args> 612 already_AddRefed<T> 613 MakeAndAddRef(Args&&... aArgs) 614 { 615 RefPtr<T> p(new T(Forward<Args>(aArgs)...)); 616 return p.forget(); 617 } 618 619 } // namespace mozilla 620 621 #endif /* mozilla_RefPtr_h */ 622