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