1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Scott Collins <scc@mozilla.org> (original author of nsCOMPtr)
24 * L. David Baron <dbaron@dbaron.org>
25 * Henri Sivonen <hsivonen@iki.fi>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #ifndef nsHtml5RefPtr_h___
42 #define nsHtml5RefPtr_h___
44 #include "nsIThread.h"
47 class nsHtml5RefPtrReleaser
: public nsRunnable
52 nsHtml5RefPtrReleaser(T
* aPtr
)
62 // template <class T> class nsHtml5RefPtrGetterAddRefs;
65 * Like nsRefPtr except release is proxied to the main thread. Mostly copied
74 assign_with_AddRef( T
* rawPtr
)
78 assign_assuming_AddRef(rawPtr
);
84 assign_assuming_AddRef(0);
85 return reinterpret_cast<void**>(&mRawPtr
);
89 assign_assuming_AddRef( T
* newPtr
)
100 nsCOMPtr
<nsIRunnable
> releaser
= new nsHtml5RefPtrReleaser
<T
>(aPtr
);
101 if (NS_FAILED(NS_DispatchToMainThread(releaser
)))
103 NS_WARNING("Failed to dispatch releaser event.");
111 typedef T element_type
;
123 // default constructor
127 nsHtml5RefPtr( const nsHtml5RefPtr
<T
>& aSmartPtr
)
128 : mRawPtr(aSmartPtr
.mRawPtr
)
135 nsHtml5RefPtr( T
* aRawPtr
)
137 // construct from a raw pointer (of the right type)
143 nsHtml5RefPtr( const already_AddRefed
<T
>& aSmartPtr
)
144 : mRawPtr(aSmartPtr
.mRawPtr
)
145 // construct from |dont_AddRef(expr)|
149 // Assignment operators
152 operator=( const nsHtml5RefPtr
<T
>& rhs
)
153 // copy assignment operator
155 assign_with_AddRef(rhs
.mRawPtr
);
161 // assign from a raw pointer (of the right type)
163 assign_with_AddRef(rhs
);
168 operator=( const already_AddRefed
<T
>& rhs
)
169 // assign from |dont_AddRef(expr)|
171 assign_assuming_AddRef(rhs
.mRawPtr
);
175 // Other pointer operators
178 swap( nsHtml5RefPtr
<T
>& rhs
)
179 // ...exchange ownership with |rhs|; can save a pair of refcount operations
181 T
* temp
= rhs
.mRawPtr
;
182 rhs
.mRawPtr
= mRawPtr
;
188 // ...exchange ownership with |rhs|; can save a pair of refcount operations
197 // return the value of mRawPtr and null out mRawPtr. Useful for
198 // already_AddRefed return values.
205 template <typename I
>
208 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
209 // Useful to avoid unnecessary AddRef/Release pairs with "out"
210 // parameters where rhs bay be a T** or an I** where I is a base class
213 NS_ASSERTION(rhs
, "Null pointer passed to forget!");
221 Prefer the implicit conversion provided automatically by |operator T*() const|.
222 Use |get()| to resolve ambiguity or to get a castable pointer.
225 return const_cast<T
*>(mRawPtr
);
230 ...makes an |nsHtml5RefPtr| act like its underlying raw pointer type whenever it
231 is used in a context where a raw pointer is expected. It is this operator
232 that makes an |nsHtml5RefPtr| substitutable for a raw pointer.
234 Prefer the implicit use of this operator to calling |get()|, except where
235 necessary to resolve ambiguity.
244 NS_PRECONDITION(mRawPtr
!= 0, "You can't dereference a NULL nsHtml5RefPtr with operator->().");
248 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
249 // broken version for IRIX
253 // This is not intended to be used by clients. See |address_of|
256 return const_cast<nsHtml5RefPtr
<T
>*>(this);
259 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
263 // This is not intended to be used by clients. See |address_of|
269 const nsHtml5RefPtr
<T
>*
271 // This is not intended to be used by clients. See |address_of|
277 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
283 NS_PRECONDITION(mRawPtr
!= 0, "You can't dereference a NULL nsHtml5RefPtr with operator*().");
290 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
291 return reinterpret_cast<T
**>(begin_assignment());
293 assign_assuming_AddRef(0);
294 return reinterpret_cast<T
**>(&mRawPtr
);
299 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
301 // This is the broken version for IRIX, which can't handle the version below.
306 address_of( const nsHtml5RefPtr
<T
>& aPtr
)
308 return aPtr
.get_address();
311 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
316 address_of( nsHtml5RefPtr
<T
>& aPtr
)
318 return aPtr
.get_address();
323 const nsHtml5RefPtr
<T
>*
324 address_of( const nsHtml5RefPtr
<T
>& aPtr
)
326 return aPtr
.get_address();
329 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
332 class nsHtml5RefPtrGetterAddRefs
336 This class is designed to be used for anonymous temporary objects in the
337 argument list of calls that return COM interface pointers, e.g.,
339 nsHtml5RefPtr<IFoo> fooP;
340 ...->GetAddRefedPointer(getter_AddRefs(fooP))
342 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
344 When initialized with a |nsHtml5RefPtr|, as in the example above, it returns
345 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
346 outer call (|GetAddRefedPointer| in this case) can fill in.
348 This type should be a nested class inside |nsHtml5RefPtr<T>|.
353 nsHtml5RefPtrGetterAddRefs( nsHtml5RefPtr
<T
>& aSmartPtr
)
354 : mTargetSmartPtr(aSmartPtr
)
356 // nothing else to do
361 return reinterpret_cast<void**>(mTargetSmartPtr
.StartAssignment());
366 return mTargetSmartPtr
.StartAssignment();
372 return *(mTargetSmartPtr
.StartAssignment());
376 nsHtml5RefPtr
<T
>& mTargetSmartPtr
;
381 nsHtml5RefPtrGetterAddRefs
<T
>
382 getter_AddRefs( nsHtml5RefPtr
<T
>& aSmartPtr
)
384 Used around a |nsHtml5RefPtr| when
385 ...makes the class |nsHtml5RefPtrGetterAddRefs<T>| invisible.
388 return nsHtml5RefPtrGetterAddRefs
<T
>(aSmartPtr
);
393 // Comparing two |nsHtml5RefPtr|s
395 template <class T
, class U
>
398 operator==( const nsHtml5RefPtr
<T
>& lhs
, const nsHtml5RefPtr
<U
>& rhs
)
400 return static_cast<const T
*>(lhs
.get()) == static_cast<const U
*>(rhs
.get());
404 template <class T
, class U
>
407 operator!=( const nsHtml5RefPtr
<T
>& lhs
, const nsHtml5RefPtr
<U
>& rhs
)
409 return static_cast<const T
*>(lhs
.get()) != static_cast<const U
*>(rhs
.get());
413 // Comparing an |nsHtml5RefPtr| to a raw pointer
415 template <class T
, class U
>
418 operator==( const nsHtml5RefPtr
<T
>& lhs
, const U
* rhs
)
420 return static_cast<const T
*>(lhs
.get()) == static_cast<const U
*>(rhs
);
423 template <class T
, class U
>
426 operator==( const U
* lhs
, const nsHtml5RefPtr
<T
>& rhs
)
428 return static_cast<const U
*>(lhs
) == static_cast<const T
*>(rhs
.get());
431 template <class T
, class U
>
434 operator!=( const nsHtml5RefPtr
<T
>& lhs
, const U
* rhs
)
436 return static_cast<const T
*>(lhs
.get()) != static_cast<const U
*>(rhs
);
439 template <class T
, class U
>
442 operator!=( const U
* lhs
, const nsHtml5RefPtr
<T
>& rhs
)
444 return static_cast<const U
*>(lhs
) != static_cast<const T
*>(rhs
.get());
447 // To avoid ambiguities caused by the presence of builtin |operator==|s
448 // creating a situation where one of the |operator==| defined above
449 // has a better conversion for one argument and the builtin has a
450 // better conversion for the other argument, define additional
451 // |operator==| without the |const| on the raw pointer.
452 // See bug 65664 for details.
454 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
455 template <class T
, class U
>
458 operator==( const nsHtml5RefPtr
<T
>& lhs
, U
* rhs
)
460 return static_cast<const T
*>(lhs
.get()) == const_cast<const U
*>(rhs
);
463 template <class T
, class U
>
466 operator==( U
* lhs
, const nsHtml5RefPtr
<T
>& rhs
)
468 return const_cast<const U
*>(lhs
) == static_cast<const T
*>(rhs
.get());
471 template <class T
, class U
>
474 operator!=( const nsHtml5RefPtr
<T
>& lhs
, U
* rhs
)
476 return static_cast<const T
*>(lhs
.get()) != const_cast<const U
*>(rhs
);
479 template <class T
, class U
>
482 operator!=( U
* lhs
, const nsHtml5RefPtr
<T
>& rhs
)
484 return const_cast<const U
*>(lhs
) != static_cast<const T
*>(rhs
.get());
490 // Comparing an |nsHtml5RefPtr| to |0|
495 operator==( const nsHtml5RefPtr
<T
>& lhs
, NSCAP_Zero
* rhs
)
496 // specifically to allow |smartPtr == 0|
498 return static_cast<const void*>(lhs
.get()) == reinterpret_cast<const void*>(rhs
);
504 operator==( NSCAP_Zero
* lhs
, const nsHtml5RefPtr
<T
>& rhs
)
505 // specifically to allow |0 == smartPtr|
507 return reinterpret_cast<const void*>(lhs
) == static_cast<const void*>(rhs
.get());
513 operator!=( const nsHtml5RefPtr
<T
>& lhs
, NSCAP_Zero
* rhs
)
514 // specifically to allow |smartPtr != 0|
516 return static_cast<const void*>(lhs
.get()) != reinterpret_cast<const void*>(rhs
);
522 operator!=( NSCAP_Zero
* lhs
, const nsHtml5RefPtr
<T
>& rhs
)
523 // specifically to allow |0 != smartPtr|
525 return reinterpret_cast<const void*>(lhs
) != static_cast<const void*>(rhs
.get());
529 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
531 // We need to explicitly define comparison operators for `int'
532 // because the compiler is lame.
537 operator==( const nsHtml5RefPtr
<T
>& lhs
, int rhs
)
538 // specifically to allow |smartPtr == 0|
540 return static_cast<const void*>(lhs
.get()) == reinterpret_cast<const void*>(rhs
);
546 operator==( int lhs
, const nsHtml5RefPtr
<T
>& rhs
)
547 // specifically to allow |0 == smartPtr|
549 return reinterpret_cast<const void*>(lhs
) == static_cast<const void*>(rhs
.get());
552 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
554 #endif // !defined(nsHtml5RefPtr_h___)