Bumping manifests a=b2g-bump
[gecko.git] / xpcom / base / nsAutoPtr.h
blob95114dc3fd5ba73a17dd72b82b122dbc10fc9ec9
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/. */
7 #ifndef nsAutoPtr_h___
8 #define nsAutoPtr_h___
10 #include "nsCOMPtr.h"
12 #include "nsCycleCollectionNoteChild.h"
13 #include "mozilla/MemoryReporting.h"
15 /*****************************************************************************/
17 // template <class T> class nsAutoPtrGetterTransfers;
19 template <class T>
20 class nsAutoPtr
22 private:
23 void**
24 begin_assignment()
26 assign(0);
27 return reinterpret_cast<void**>(&mRawPtr);
30 void
31 assign(T* aNewPtr)
33 T* oldPtr = mRawPtr;
35 if (aNewPtr && aNewPtr == oldPtr) {
36 NS_RUNTIMEABORT("Logic flaw in the caller");
39 mRawPtr = aNewPtr;
40 delete oldPtr;
43 // |class Ptr| helps us prevent implicit "copy construction"
44 // through |operator T*() const| from a |const nsAutoPtr<T>|
45 // because two implicit conversions in a row aren't allowed.
46 // It still allows assignment from T* through implicit conversion
47 // from |T*| to |nsAutoPtr<T>::Ptr|
48 class Ptr
50 public:
51 MOZ_IMPLICIT Ptr(T* aPtr)
52 : mPtr(aPtr)
56 operator T*() const
58 return mPtr;
61 private:
62 T* mPtr;
65 private:
66 T* mRawPtr;
68 public:
69 typedef T element_type;
71 ~nsAutoPtr()
73 delete mRawPtr;
76 // Constructors
78 nsAutoPtr()
79 : mRawPtr(0)
80 // default constructor
84 MOZ_IMPLICIT nsAutoPtr(Ptr aRawPtr)
85 : mRawPtr(aRawPtr)
86 // construct from a raw pointer (of the right type)
90 // This constructor shouldn't exist; we should just use the &&
91 // constructor.
92 nsAutoPtr(nsAutoPtr<T>& aSmartPtr)
93 : mRawPtr(aSmartPtr.forget())
94 // Construct by transferring ownership from another smart pointer.
98 nsAutoPtr(nsAutoPtr<T>&& aSmartPtr)
99 : mRawPtr(aSmartPtr.forget())
100 // Construct by transferring ownership from another smart pointer.
104 // Assignment operators
106 nsAutoPtr<T>&
107 operator=(T* aRhs)
108 // assign from a raw pointer (of the right type)
110 assign(aRhs);
111 return *this;
114 nsAutoPtr<T>& operator=(nsAutoPtr<T>& aRhs)
115 // assign by transferring ownership from another smart pointer.
117 assign(aRhs.forget());
118 return *this;
121 nsAutoPtr<T>& operator=(nsAutoPtr<T>&& aRhs)
123 assign(aRhs.forget());
124 return *this;
127 // Other pointer operators
130 get() const
132 Prefer the implicit conversion provided automatically by
133 |operator T*() const|. Use |get()| _only_ to resolve
134 ambiguity.
137 return mRawPtr;
140 operator T*() const
142 ...makes an |nsAutoPtr| act like its underlying raw pointer
143 type whenever it is used in a context where a raw pointer
144 is expected. It is this operator that makes an |nsAutoPtr|
145 substitutable for a raw pointer.
147 Prefer the implicit use of this operator to calling |get()|,
148 except where necessary to resolve ambiguity.
151 return get();
155 forget()
157 T* temp = mRawPtr;
158 mRawPtr = 0;
159 return temp;
163 operator->() const
165 NS_PRECONDITION(mRawPtr != 0,
166 "You can't dereference a NULL nsAutoPtr with operator->().");
167 return get();
170 // This operator is needed for gcc <= 4.0.* and for Sun Studio; it
171 // causes internal compiler errors for some MSVC versions. (It's not
172 // clear to me whether it should be needed.)
173 #ifndef _MSC_VER
174 template <class U, class V>
176 operator->*(U V::* aMember)
178 NS_PRECONDITION(mRawPtr != 0,
179 "You can't dereference a NULL nsAutoPtr with operator->*().");
180 return get()->*aMember;
182 #endif
184 nsAutoPtr<T>*
185 get_address()
186 // This is not intended to be used by clients. See |address_of|
187 // below.
189 return this;
192 const nsAutoPtr<T>*
193 get_address() const
194 // This is not intended to be used by clients. See |address_of|
195 // below.
197 return this;
200 public:
202 operator*() const
204 NS_PRECONDITION(mRawPtr != 0,
205 "You can't dereference a NULL nsAutoPtr with operator*().");
206 return *get();
210 StartAssignment()
212 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
213 return reinterpret_cast<T**>(begin_assignment());
214 #else
215 assign(0);
216 return reinterpret_cast<T**>(&mRawPtr);
217 #endif
221 template <class T>
222 inline nsAutoPtr<T>*
223 address_of(nsAutoPtr<T>& aPtr)
225 return aPtr.get_address();
228 template <class T>
229 inline const nsAutoPtr<T>*
230 address_of(const nsAutoPtr<T>& aPtr)
232 return aPtr.get_address();
235 template <class T>
236 class nsAutoPtrGetterTransfers
240 This class is designed to be used for anonymous temporary objects in the
241 argument list of calls that return COM interface pointers, e.g.,
243 nsAutoPtr<IFoo> fooP;
244 ...->GetTransferedPointer(getter_Transfers(fooP))
246 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
248 When initialized with a |nsAutoPtr|, as in the example above, it returns
249 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
250 outer call (|GetTransferedPointer| in this case) can fill in.
252 This type should be a nested class inside |nsAutoPtr<T>|.
255 public:
256 explicit
257 nsAutoPtrGetterTransfers(nsAutoPtr<T>& aSmartPtr)
258 : mTargetSmartPtr(aSmartPtr)
260 // nothing else to do
263 operator void**()
265 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
268 operator T**()
270 return mTargetSmartPtr.StartAssignment();
274 operator*()
276 return *(mTargetSmartPtr.StartAssignment());
279 private:
280 nsAutoPtr<T>& mTargetSmartPtr;
283 template <class T>
284 inline nsAutoPtrGetterTransfers<T>
285 getter_Transfers(nsAutoPtr<T>& aSmartPtr)
287 Used around a |nsAutoPtr| when
288 ...makes the class |nsAutoPtrGetterTransfers<T>| invisible.
291 return nsAutoPtrGetterTransfers<T>(aSmartPtr);
296 // Comparing two |nsAutoPtr|s
298 template <class T, class U>
299 inline bool
300 operator==(const nsAutoPtr<T>& aLhs, const nsAutoPtr<U>& aRhs)
302 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
306 template <class T, class U>
307 inline bool
308 operator!=(const nsAutoPtr<T>& aLhs, const nsAutoPtr<U>& aRhs)
310 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
314 // Comparing an |nsAutoPtr| to a raw pointer
316 template <class T, class U>
317 inline bool
318 operator==(const nsAutoPtr<T>& aLhs, const U* aRhs)
320 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs);
323 template <class T, class U>
324 inline bool
325 operator==(const U* aLhs, const nsAutoPtr<T>& aRhs)
327 return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
330 template <class T, class U>
331 inline bool
332 operator!=(const nsAutoPtr<T>& aLhs, const U* aRhs)
334 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs);
337 template <class T, class U>
338 inline bool
339 operator!=(const U* aLhs, const nsAutoPtr<T>& aRhs)
341 return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
344 template <class T, class U>
345 inline bool
346 operator==(const nsAutoPtr<T>& aLhs, U* aRhs)
348 return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
351 template <class T, class U>
352 inline bool
353 operator==(U* aLhs, const nsAutoPtr<T>& aRhs)
355 return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
358 template <class T, class U>
359 inline bool
360 operator!=(const nsAutoPtr<T>& aLhs, U* aRhs)
362 return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
365 template <class T, class U>
366 inline bool
367 operator!=(U* aLhs, const nsAutoPtr<T>& aRhs)
369 return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
374 // Comparing an |nsAutoPtr| to |0|
376 template <class T>
377 inline bool
378 operator==(const nsAutoPtr<T>& aLhs, NSCAP_Zero* aRhs)
379 // specifically to allow |smartPtr == 0|
381 return static_cast<const void*>(aLhs.get()) == reinterpret_cast<const void*>(aRhs);
384 template <class T>
385 inline bool
386 operator==(NSCAP_Zero* aLhs, const nsAutoPtr<T>& aRhs)
387 // specifically to allow |0 == smartPtr|
389 return reinterpret_cast<const void*>(aLhs) == static_cast<const void*>(aRhs.get());
392 template <class T>
393 inline bool
394 operator!=(const nsAutoPtr<T>& aLhs, NSCAP_Zero* aRhs)
395 // specifically to allow |smartPtr != 0|
397 return static_cast<const void*>(aLhs.get()) != reinterpret_cast<const void*>(aRhs);
400 template <class T>
401 inline bool
402 operator!=(NSCAP_Zero* aLhs, const nsAutoPtr<T>& aRhs)
403 // specifically to allow |0 != smartPtr|
405 return reinterpret_cast<const void*>(aLhs) != static_cast<const void*>(aRhs.get());
409 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
411 // We need to explicitly define comparison operators for `int'
412 // because the compiler is lame.
414 template <class T>
415 inline bool
416 operator==(const nsAutoPtr<T>& aLhs, int aRhs)
417 // specifically to allow |smartPtr == 0|
419 return static_cast<const void*>(aLhs.get()) == reinterpret_cast<const void*>(aRhs);
422 template <class T>
423 inline bool
424 operator==(int aLhs, const nsAutoPtr<T>& aRhs)
425 // specifically to allow |0 == smartPtr|
427 return reinterpret_cast<const void*>(aLhs) == static_cast<const void*>(aRhs.get());
430 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
432 /*****************************************************************************/
434 // template <class T> class nsAutoArrayPtrGetterTransfers;
436 template <class T>
437 class nsAutoArrayPtr
439 private:
440 void**
441 begin_assignment()
443 assign(0);
444 return reinterpret_cast<void**>(&mRawPtr);
447 void
448 assign(T* aNewPtr)
450 T* oldPtr = mRawPtr;
451 mRawPtr = aNewPtr;
452 delete [] oldPtr;
455 private:
456 T* mRawPtr;
458 public:
459 typedef T element_type;
461 ~nsAutoArrayPtr()
463 delete [] mRawPtr;
466 // Constructors
468 nsAutoArrayPtr()
469 : mRawPtr(0)
470 // default constructor
474 MOZ_IMPLICIT nsAutoArrayPtr(T* aRawPtr)
475 : mRawPtr(aRawPtr)
476 // construct from a raw pointer (of the right type)
480 nsAutoArrayPtr(nsAutoArrayPtr<T>& aSmartPtr)
481 : mRawPtr(aSmartPtr.forget())
482 // Construct by transferring ownership from another smart pointer.
487 // Assignment operators
489 nsAutoArrayPtr<T>&
490 operator=(T* aRhs)
491 // assign from a raw pointer (of the right type)
493 assign(aRhs);
494 return *this;
497 nsAutoArrayPtr<T>& operator=(nsAutoArrayPtr<T>& aRhs)
498 // assign by transferring ownership from another smart pointer.
500 assign(aRhs.forget());
501 return *this;
504 // Other pointer operators
507 get() const
509 Prefer the implicit conversion provided automatically by
510 |operator T*() const|. Use |get()| _only_ to resolve
511 ambiguity.
514 return mRawPtr;
517 operator T*() const
519 ...makes an |nsAutoArrayPtr| act like its underlying raw pointer
520 type whenever it is used in a context where a raw pointer
521 is expected. It is this operator that makes an |nsAutoArrayPtr|
522 substitutable for a raw pointer.
524 Prefer the implicit use of this operator to calling |get()|,
525 except where necessary to resolve ambiguity.
528 return get();
532 forget()
534 T* temp = mRawPtr;
535 mRawPtr = 0;
536 return temp;
540 operator->() const
542 NS_PRECONDITION(mRawPtr != 0,
543 "You can't dereference a NULL nsAutoArrayPtr with operator->().");
544 return get();
547 nsAutoArrayPtr<T>*
548 get_address()
549 // This is not intended to be used by clients. See |address_of|
550 // below.
552 return this;
555 const nsAutoArrayPtr<T>*
556 get_address() const
557 // This is not intended to be used by clients. See |address_of|
558 // below.
560 return this;
563 public:
565 operator*() const
567 NS_PRECONDITION(mRawPtr != 0,
568 "You can't dereference a NULL nsAutoArrayPtr with operator*().");
569 return *get();
573 StartAssignment()
575 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
576 return reinterpret_cast<T**>(begin_assignment());
577 #else
578 assign(0);
579 return reinterpret_cast<T**>(&mRawPtr);
580 #endif
583 size_t
584 SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
586 return aMallocSizeOf(mRawPtr);
589 size_t
590 SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
592 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
596 template <class T>
597 inline nsAutoArrayPtr<T>*
598 address_of(nsAutoArrayPtr<T>& aPtr)
600 return aPtr.get_address();
603 template <class T>
604 inline const nsAutoArrayPtr<T>*
605 address_of(const nsAutoArrayPtr<T>& aPtr)
607 return aPtr.get_address();
610 template <class T>
611 class nsAutoArrayPtrGetterTransfers
615 This class is designed to be used for anonymous temporary objects in the
616 argument list of calls that return COM interface pointers, e.g.,
618 nsAutoArrayPtr<IFoo> fooP;
619 ...->GetTransferedPointer(getter_Transfers(fooP))
621 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_Transfers()| instead.
623 When initialized with a |nsAutoArrayPtr|, as in the example above, it returns
624 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
625 outer call (|GetTransferedPointer| in this case) can fill in.
627 This type should be a nested class inside |nsAutoArrayPtr<T>|.
630 public:
631 explicit
632 nsAutoArrayPtrGetterTransfers(nsAutoArrayPtr<T>& aSmartPtr)
633 : mTargetSmartPtr(aSmartPtr)
635 // nothing else to do
638 operator void**()
640 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
643 operator T**()
645 return mTargetSmartPtr.StartAssignment();
649 operator*()
651 return *(mTargetSmartPtr.StartAssignment());
654 private:
655 nsAutoArrayPtr<T>& mTargetSmartPtr;
658 template <class T>
659 inline nsAutoArrayPtrGetterTransfers<T>
660 getter_Transfers(nsAutoArrayPtr<T>& aSmartPtr)
662 Used around a |nsAutoArrayPtr| when
663 ...makes the class |nsAutoArrayPtrGetterTransfers<T>| invisible.
666 return nsAutoArrayPtrGetterTransfers<T>(aSmartPtr);
671 // Comparing two |nsAutoArrayPtr|s
673 template <class T, class U>
674 inline bool
675 operator==(const nsAutoArrayPtr<T>& aLhs, const nsAutoArrayPtr<U>& aRhs)
677 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
681 template <class T, class U>
682 inline bool
683 operator!=(const nsAutoArrayPtr<T>& aLhs, const nsAutoArrayPtr<U>& aRhs)
685 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
689 // Comparing an |nsAutoArrayPtr| to a raw pointer
691 template <class T, class U>
692 inline bool
693 operator==(const nsAutoArrayPtr<T>& aLhs, const U* aRhs)
695 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs);
698 template <class T, class U>
699 inline bool
700 operator==(const U* aLhs, const nsAutoArrayPtr<T>& aRhs)
702 return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
705 template <class T, class U>
706 inline bool
707 operator!=(const nsAutoArrayPtr<T>& aLhs, const U* aRhs)
709 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs);
712 template <class T, class U>
713 inline bool
714 operator!=(const U* aLhs, const nsAutoArrayPtr<T>& aRhs)
716 return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
719 template <class T, class U>
720 inline bool
721 operator==(const nsAutoArrayPtr<T>& aLhs, U* aRhs)
723 return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
726 template <class T, class U>
727 inline bool
728 operator==(U* aLhs, const nsAutoArrayPtr<T>& aRhs)
730 return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
733 template <class T, class U>
734 inline bool
735 operator!=(const nsAutoArrayPtr<T>& aLhs, U* aRhs)
737 return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
740 template <class T, class U>
741 inline bool
742 operator!=(U* aLhs, const nsAutoArrayPtr<T>& aRhs)
744 return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
749 // Comparing an |nsAutoArrayPtr| to |0|
751 template <class T>
752 inline bool
753 operator==(const nsAutoArrayPtr<T>& aLhs, NSCAP_Zero* aRhs)
754 // specifically to allow |smartPtr == 0|
756 return static_cast<const void*>(aLhs.get()) == reinterpret_cast<const void*>(aRhs);
759 template <class T>
760 inline bool
761 operator==(NSCAP_Zero* aLhs, const nsAutoArrayPtr<T>& aRhs)
762 // specifically to allow |0 == smartPtr|
764 return reinterpret_cast<const void*>(aLhs) == static_cast<const void*>(aRhs.get());
767 template <class T>
768 inline bool
769 operator!=(const nsAutoArrayPtr<T>& aLhs, NSCAP_Zero* aRhs)
770 // specifically to allow |smartPtr != 0|
772 return static_cast<const void*>(aLhs.get()) != reinterpret_cast<const void*>(aRhs);
775 template <class T>
776 inline bool
777 operator!=(NSCAP_Zero* aLhs, const nsAutoArrayPtr<T>& aRhs)
778 // specifically to allow |0 != smartPtr|
780 return reinterpret_cast<const void*>(aLhs) != static_cast<const void*>(aRhs.get());
784 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
786 // We need to explicitly define comparison operators for `int'
787 // because the compiler is lame.
789 template <class T>
790 inline bool
791 operator==(const nsAutoArrayPtr<T>& aLhs, int aRhs)
792 // specifically to allow |smartPtr == 0|
794 return static_cast<const void*>(aLhs.get()) == reinterpret_cast<const void*>(aRhs);
797 template <class T>
798 inline bool
799 operator==(int aLhs, const nsAutoArrayPtr<T>& aRhs)
800 // specifically to allow |0 == smartPtr|
802 return reinterpret_cast<const void*>(aLhs) == static_cast<const void*>(aRhs.get());
805 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
808 /*****************************************************************************/
810 // template <class T> class nsRefPtrGetterAddRefs;
812 template <class T>
813 class nsRefPtr
815 private:
817 void
818 assign_with_AddRef(T* aRawPtr)
820 if (aRawPtr) {
821 aRawPtr->AddRef();
823 assign_assuming_AddRef(aRawPtr);
826 void**
827 begin_assignment()
829 assign_assuming_AddRef(0);
830 return reinterpret_cast<void**>(&mRawPtr);
833 void
834 assign_assuming_AddRef(T* aNewPtr)
836 T* oldPtr = mRawPtr;
837 mRawPtr = aNewPtr;
838 if (oldPtr) {
839 oldPtr->Release();
843 private:
844 T* mRawPtr;
846 public:
847 typedef T element_type;
849 ~nsRefPtr()
851 if (mRawPtr) {
852 mRawPtr->Release();
856 // Constructors
858 nsRefPtr()
859 : mRawPtr(0)
860 // default constructor
864 nsRefPtr(const nsRefPtr<T>& aSmartPtr)
865 : mRawPtr(aSmartPtr.mRawPtr)
866 // copy-constructor
868 if (mRawPtr) {
869 mRawPtr->AddRef();
873 nsRefPtr(nsRefPtr<T>&& aRefPtr)
874 : mRawPtr(aRefPtr.mRawPtr)
876 aRefPtr.mRawPtr = nullptr;
879 // construct from a raw pointer (of the right type)
881 MOZ_IMPLICIT nsRefPtr(T* aRawPtr)
882 : mRawPtr(aRawPtr)
884 if (mRawPtr) {
885 mRawPtr->AddRef();
889 template <typename I>
890 nsRefPtr(already_AddRefed<I>& aSmartPtr)
891 : mRawPtr(aSmartPtr.take())
892 // construct from |already_AddRefed|
896 template <typename I>
897 nsRefPtr(already_AddRefed<I>&& aSmartPtr)
898 : mRawPtr(aSmartPtr.take())
899 // construct from |otherRefPtr.forget()|
903 MOZ_IMPLICIT nsRefPtr(const nsCOMPtr_helper& aHelper)
905 void* newRawPtr;
906 if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
907 newRawPtr = 0;
909 mRawPtr = static_cast<T*>(newRawPtr);
912 // Assignment operators
914 nsRefPtr<T>&
915 operator=(const nsRefPtr<T>& aRhs)
916 // copy assignment operator
918 assign_with_AddRef(aRhs.mRawPtr);
919 return *this;
922 nsRefPtr<T>&
923 operator=(T* aRhs)
924 // assign from a raw pointer (of the right type)
926 assign_with_AddRef(aRhs);
927 return *this;
930 template <typename I>
931 nsRefPtr<T>&
932 operator=(already_AddRefed<I>& aRhs)
933 // assign from |already_AddRefed|
935 assign_assuming_AddRef(aRhs.take());
936 return *this;
939 template <typename I>
940 nsRefPtr<T>&
941 operator=(already_AddRefed<I> && aRhs)
942 // assign from |otherRefPtr.forget()|
944 assign_assuming_AddRef(aRhs.take());
945 return *this;
948 nsRefPtr<T>&
949 operator=(const nsCOMPtr_helper& aHelper)
951 void* newRawPtr;
952 if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
953 newRawPtr = 0;
955 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
956 return *this;
959 nsRefPtr<T>&
960 operator=(nsRefPtr<T> && aRefPtr)
962 assign_assuming_AddRef(aRefPtr.mRawPtr);
963 aRefPtr.mRawPtr = nullptr;
964 return *this;
967 // Other pointer operators
969 void
970 swap(nsRefPtr<T>& aRhs)
971 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
973 T* temp = aRhs.mRawPtr;
974 aRhs.mRawPtr = mRawPtr;
975 mRawPtr = temp;
978 void
979 swap(T*& aRhs)
980 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
982 T* temp = aRhs;
983 aRhs = mRawPtr;
984 mRawPtr = temp;
987 already_AddRefed<T>
988 forget()
989 // return the value of mRawPtr and null out mRawPtr. Useful for
990 // already_AddRefed return values.
992 T* temp = 0;
993 swap(temp);
994 return already_AddRefed<T>(temp);
997 template <typename I>
998 void
999 forget(I** aRhs)
1000 // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
1001 // Useful to avoid unnecessary AddRef/Release pairs with "out"
1002 // parameters where aRhs bay be a T** or an I** where I is a base class
1003 // of T.
1005 NS_ASSERTION(aRhs, "Null pointer passed to forget!");
1006 *aRhs = mRawPtr;
1007 mRawPtr = 0;
1011 get() const
1013 Prefer the implicit conversion provided automatically by |operator T*() const|.
1014 Use |get()| to resolve ambiguity or to get a castable pointer.
1017 return const_cast<T*>(mRawPtr);
1020 operator T*() const
1022 ...makes an |nsRefPtr| act like its underlying raw pointer type whenever it
1023 is used in a context where a raw pointer is expected. It is this operator
1024 that makes an |nsRefPtr| substitutable for a raw pointer.
1026 Prefer the implicit use of this operator to calling |get()|, except where
1027 necessary to resolve ambiguity.
1030 return get();
1034 operator->() const
1036 NS_PRECONDITION(mRawPtr != 0,
1037 "You can't dereference a NULL nsRefPtr with operator->().");
1038 return get();
1041 // This operator is needed for gcc <= 4.0.* and for Sun Studio; it
1042 // causes internal compiler errors for some MSVC versions. (It's not
1043 // clear to me whether it should be needed.)
1044 #ifndef _MSC_VER
1045 template <class U, class V>
1047 operator->*(U V::* aMember)
1049 NS_PRECONDITION(mRawPtr != 0,
1050 "You can't dereference a NULL nsRefPtr with operator->*().");
1051 return get()->*aMember;
1053 #endif
1055 nsRefPtr<T>*
1056 get_address()
1057 // This is not intended to be used by clients. See |address_of|
1058 // below.
1060 return this;
1063 const nsRefPtr<T>*
1064 get_address() const
1065 // This is not intended to be used by clients. See |address_of|
1066 // below.
1068 return this;
1071 public:
1073 operator*() const
1075 NS_PRECONDITION(mRawPtr != 0,
1076 "You can't dereference a NULL nsRefPtr with operator*().");
1077 return *get();
1081 StartAssignment()
1083 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
1084 return reinterpret_cast<T**>(begin_assignment());
1085 #else
1086 assign_assuming_AddRef(0);
1087 return reinterpret_cast<T**>(&mRawPtr);
1088 #endif
1092 template <typename T>
1093 inline void
1094 ImplCycleCollectionUnlink(nsRefPtr<T>& aField)
1096 aField = nullptr;
1099 template <typename T>
1100 inline void
1101 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
1102 nsRefPtr<T>& aField,
1103 const char* aName,
1104 uint32_t aFlags = 0)
1106 CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
1109 template <class T>
1110 inline nsRefPtr<T>*
1111 address_of(nsRefPtr<T>& aPtr)
1113 return aPtr.get_address();
1116 template <class T>
1117 inline const nsRefPtr<T>*
1118 address_of(const nsRefPtr<T>& aPtr)
1120 return aPtr.get_address();
1123 template <class T>
1124 class nsRefPtrGetterAddRefs
1128 This class is designed to be used for anonymous temporary objects in the
1129 argument list of calls that return COM interface pointers, e.g.,
1131 nsRefPtr<IFoo> fooP;
1132 ...->GetAddRefedPointer(getter_AddRefs(fooP))
1134 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
1136 When initialized with a |nsRefPtr|, as in the example above, it returns
1137 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
1138 outer call (|GetAddRefedPointer| in this case) can fill in.
1140 This type should be a nested class inside |nsRefPtr<T>|.
1143 public:
1144 explicit
1145 nsRefPtrGetterAddRefs(nsRefPtr<T>& aSmartPtr)
1146 : mTargetSmartPtr(aSmartPtr)
1148 // nothing else to do
1151 operator void**()
1153 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
1156 operator T**()
1158 return mTargetSmartPtr.StartAssignment();
1162 operator*()
1164 return *(mTargetSmartPtr.StartAssignment());
1167 private:
1168 nsRefPtr<T>& mTargetSmartPtr;
1171 template <class T>
1172 inline nsRefPtrGetterAddRefs<T>
1173 getter_AddRefs(nsRefPtr<T>& aSmartPtr)
1175 Used around a |nsRefPtr| when
1176 ...makes the class |nsRefPtrGetterAddRefs<T>| invisible.
1179 return nsRefPtrGetterAddRefs<T>(aSmartPtr);
1184 // Comparing two |nsRefPtr|s
1186 template <class T, class U>
1187 inline bool
1188 operator==(const nsRefPtr<T>& aLhs, const nsRefPtr<U>& aRhs)
1190 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
1194 template <class T, class U>
1195 inline bool
1196 operator!=(const nsRefPtr<T>& aLhs, const nsRefPtr<U>& aRhs)
1198 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
1202 // Comparing an |nsRefPtr| to a raw pointer
1204 template <class T, class U>
1205 inline bool
1206 operator==(const nsRefPtr<T>& aLhs, const U* aRhs)
1208 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs);
1211 template <class T, class U>
1212 inline bool
1213 operator==(const U* aLhs, const nsRefPtr<T>& aRhs)
1215 return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
1218 template <class T, class U>
1219 inline bool
1220 operator!=(const nsRefPtr<T>& aLhs, const U* aRhs)
1222 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs);
1225 template <class T, class U>
1226 inline bool
1227 operator!=(const U* aLhs, const nsRefPtr<T>& aRhs)
1229 return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
1232 template <class T, class U>
1233 inline bool
1234 operator==(const nsRefPtr<T>& aLhs, U* aRhs)
1236 return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
1239 template <class T, class U>
1240 inline bool
1241 operator==(U* aLhs, const nsRefPtr<T>& aRhs)
1243 return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
1246 template <class T, class U>
1247 inline bool
1248 operator!=(const nsRefPtr<T>& aLhs, U* aRhs)
1250 return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
1253 template <class T, class U>
1254 inline bool
1255 operator!=(U* aLhs, const nsRefPtr<T>& aRhs)
1257 return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
1262 // Comparing an |nsRefPtr| to |0|
1264 template <class T>
1265 inline bool
1266 operator==(const nsRefPtr<T>& aLhs, NSCAP_Zero* aRhs)
1267 // specifically to allow |smartPtr == 0|
1269 return static_cast<const void*>(aLhs.get()) == reinterpret_cast<const void*>(aRhs);
1272 template <class T>
1273 inline bool
1274 operator==(NSCAP_Zero* aLhs, const nsRefPtr<T>& aRhs)
1275 // specifically to allow |0 == smartPtr|
1277 return reinterpret_cast<const void*>(aLhs) == static_cast<const void*>(aRhs.get());
1280 template <class T>
1281 inline bool
1282 operator!=(const nsRefPtr<T>& aLhs, NSCAP_Zero* aRhs)
1283 // specifically to allow |smartPtr != 0|
1285 return static_cast<const void*>(aLhs.get()) != reinterpret_cast<const void*>(aRhs);
1288 template <class T>
1289 inline bool
1290 operator!=(NSCAP_Zero* aLhs, const nsRefPtr<T>& aRhs)
1291 // specifically to allow |0 != smartPtr|
1293 return reinterpret_cast<const void*>(aLhs) != static_cast<const void*>(aRhs.get());
1297 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
1299 // We need to explicitly define comparison operators for `int'
1300 // because the compiler is lame.
1302 template <class T>
1303 inline bool
1304 operator==(const nsRefPtr<T>& aLhs, int aRhs)
1305 // specifically to allow |smartPtr == 0|
1307 return static_cast<const void*>(aLhs.get()) == reinterpret_cast<const void*>(aRhs);
1310 template <class T>
1311 inline bool
1312 operator==(int aLhs, const nsRefPtr<T>& aRhs)
1313 // specifically to allow |0 == smartPtr|
1315 return reinterpret_cast<const void*>(aLhs) == static_cast<const void*>(aRhs.get());
1318 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
1320 template <class SourceType, class DestinationType>
1321 inline nsresult
1322 CallQueryInterface(nsRefPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr)
1324 return CallQueryInterface(aSourcePtr.get(), aDestPtr);
1327 /*****************************************************************************/
1329 template<class T>
1330 class nsQueryObject : public nsCOMPtr_helper
1332 public:
1333 explicit nsQueryObject(T* aRawPtr)
1334 : mRawPtr(aRawPtr)
1338 virtual nsresult NS_FASTCALL operator()(const nsIID& aIID,
1339 void** aResult) const
1341 nsresult status = mRawPtr ? mRawPtr->QueryInterface(aIID, aResult)
1342 : NS_ERROR_NULL_POINTER;
1343 return status;
1345 private:
1346 T* mRawPtr;
1349 template<class T>
1350 class nsQueryObjectWithError : public nsCOMPtr_helper
1352 public:
1353 nsQueryObjectWithError(T* aRawPtr, nsresult* aErrorPtr)
1354 : mRawPtr(aRawPtr), mErrorPtr(aErrorPtr)
1358 virtual nsresult NS_FASTCALL operator()(const nsIID& aIID,
1359 void** aResult) const
1361 nsresult status = mRawPtr ? mRawPtr->QueryInterface(aIID, aResult)
1362 : NS_ERROR_NULL_POINTER;
1363 if (mErrorPtr) {
1364 *mErrorPtr = status;
1366 return status;
1368 private:
1369 T* mRawPtr;
1370 nsresult* mErrorPtr;
1373 template<class T>
1374 inline nsQueryObject<T>
1375 do_QueryObject(T* aRawPtr)
1377 return nsQueryObject<T>(aRawPtr);
1380 template<class T>
1381 inline nsQueryObject<T>
1382 do_QueryObject(nsCOMPtr<T>& aRawPtr)
1384 return nsQueryObject<T>(aRawPtr);
1387 template<class T>
1388 inline nsQueryObject<T>
1389 do_QueryObject(nsRefPtr<T>& aRawPtr)
1391 return nsQueryObject<T>(aRawPtr);
1394 template<class T>
1395 inline nsQueryObjectWithError<T>
1396 do_QueryObject(T* aRawPtr, nsresult* aErrorPtr)
1398 return nsQueryObjectWithError<T>(aRawPtr, aErrorPtr);
1401 template<class T>
1402 inline nsQueryObjectWithError<T>
1403 do_QueryObject(nsCOMPtr<T>& aRawPtr, nsresult* aErrorPtr)
1405 return nsQueryObjectWithError<T>(aRawPtr, aErrorPtr);
1408 template<class T>
1409 inline nsQueryObjectWithError<T>
1410 do_QueryObject(nsRefPtr<T>& aRawPtr, nsresult* aErrorPtr)
1412 return nsQueryObjectWithError<T>(aRawPtr, aErrorPtr);
1415 /*****************************************************************************/
1417 #endif // !defined(nsAutoPtr_h___)