Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / parser / html / nsHtml5RefPtr.h
blobffa9ebbc52dd40a0b9cc46bf3589573a86aee903
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
13 * License.
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.
22 * Contributor(s):
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"
46 template <class T>
47 class nsHtml5RefPtrReleaser : public nsRunnable
49 private:
50 T* mPtr;
51 public:
52 nsHtml5RefPtrReleaser(T* aPtr)
53 : mPtr(aPtr)
55 NS_IMETHODIMP Run()
57 mPtr->Release();
58 return NS_OK;
62 // template <class T> class nsHtml5RefPtrGetterAddRefs;
64 /**
65 * Like nsRefPtr except release is proxied to the main thread. Mostly copied
66 * from nsRefPtr.
68 template <class T>
69 class nsHtml5RefPtr
71 private:
73 void
74 assign_with_AddRef( T* rawPtr )
76 if ( rawPtr )
77 rawPtr->AddRef();
78 assign_assuming_AddRef(rawPtr);
81 void**
82 begin_assignment()
84 assign_assuming_AddRef(0);
85 return reinterpret_cast<void**>(&mRawPtr);
88 void
89 assign_assuming_AddRef( T* newPtr )
91 T* oldPtr = mRawPtr;
92 mRawPtr = newPtr;
93 if ( oldPtr )
94 release(oldPtr);
97 void
98 release( T* aPtr )
100 nsCOMPtr<nsIRunnable> releaser = new nsHtml5RefPtrReleaser<T>(aPtr);
101 if (NS_FAILED(NS_DispatchToMainThread(releaser)))
103 NS_WARNING("Failed to dispatch releaser event.");
107 private:
108 T* mRawPtr;
110 public:
111 typedef T element_type;
113 ~nsHtml5RefPtr()
115 if ( mRawPtr )
116 release(mRawPtr);
119 // Constructors
121 nsHtml5RefPtr()
122 : mRawPtr(0)
123 // default constructor
127 nsHtml5RefPtr( const nsHtml5RefPtr<T>& aSmartPtr )
128 : mRawPtr(aSmartPtr.mRawPtr)
129 // copy-constructor
131 if ( mRawPtr )
132 mRawPtr->AddRef();
135 nsHtml5RefPtr( T* aRawPtr )
136 : mRawPtr(aRawPtr)
137 // construct from a raw pointer (of the right type)
139 if ( mRawPtr )
140 mRawPtr->AddRef();
143 nsHtml5RefPtr( const already_AddRefed<T>& aSmartPtr )
144 : mRawPtr(aSmartPtr.mRawPtr)
145 // construct from |dont_AddRef(expr)|
149 // Assignment operators
151 nsHtml5RefPtr<T>&
152 operator=( const nsHtml5RefPtr<T>& rhs )
153 // copy assignment operator
155 assign_with_AddRef(rhs.mRawPtr);
156 return *this;
159 nsHtml5RefPtr<T>&
160 operator=( T* rhs )
161 // assign from a raw pointer (of the right type)
163 assign_with_AddRef(rhs);
164 return *this;
167 nsHtml5RefPtr<T>&
168 operator=( const already_AddRefed<T>& rhs )
169 // assign from |dont_AddRef(expr)|
171 assign_assuming_AddRef(rhs.mRawPtr);
172 return *this;
175 // Other pointer operators
177 void
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;
183 mRawPtr = temp;
186 void
187 swap( T*& rhs )
188 // ...exchange ownership with |rhs|; can save a pair of refcount operations
190 T* temp = rhs;
191 rhs = mRawPtr;
192 mRawPtr = temp;
195 already_AddRefed<T>
196 forget()
197 // return the value of mRawPtr and null out mRawPtr. Useful for
198 // already_AddRefed return values.
200 T* temp = 0;
201 swap(temp);
202 return temp;
205 template <typename I>
206 void
207 forget( I** rhs)
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
211 // of T.
213 NS_ASSERTION(rhs, "Null pointer passed to forget!");
214 *rhs = mRawPtr;
215 mRawPtr = 0;
219 get() const
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);
228 operator T*() const
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.
238 return get();
242 operator->() const
244 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsHtml5RefPtr with operator->().");
245 return get();
248 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
249 // broken version for IRIX
251 nsHtml5RefPtr<T>*
252 get_address() const
253 // This is not intended to be used by clients. See |address_of|
254 // below.
256 return const_cast<nsHtml5RefPtr<T>*>(this);
259 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
261 nsHtml5RefPtr<T>*
262 get_address()
263 // This is not intended to be used by clients. See |address_of|
264 // below.
266 return this;
269 const nsHtml5RefPtr<T>*
270 get_address() const
271 // This is not intended to be used by clients. See |address_of|
272 // below.
274 return this;
277 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
279 public:
281 operator*() const
283 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsHtml5RefPtr with operator*().");
284 return *get();
288 StartAssignment()
290 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
291 return reinterpret_cast<T**>(begin_assignment());
292 #else
293 assign_assuming_AddRef(0);
294 return reinterpret_cast<T**>(&mRawPtr);
295 #endif
299 #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
301 // This is the broken version for IRIX, which can't handle the version below.
303 template <class T>
304 inline
305 nsHtml5RefPtr<T>*
306 address_of( const nsHtml5RefPtr<T>& aPtr )
308 return aPtr.get_address();
311 #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
313 template <class T>
314 inline
315 nsHtml5RefPtr<T>*
316 address_of( nsHtml5RefPtr<T>& aPtr )
318 return aPtr.get_address();
321 template <class T>
322 inline
323 const nsHtml5RefPtr<T>*
324 address_of( const nsHtml5RefPtr<T>& aPtr )
326 return aPtr.get_address();
329 #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
331 template <class T>
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>|.
351 public:
352 explicit
353 nsHtml5RefPtrGetterAddRefs( nsHtml5RefPtr<T>& aSmartPtr )
354 : mTargetSmartPtr(aSmartPtr)
356 // nothing else to do
359 operator void**()
361 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
364 operator T**()
366 return mTargetSmartPtr.StartAssignment();
370 operator*()
372 return *(mTargetSmartPtr.StartAssignment());
375 private:
376 nsHtml5RefPtr<T>& mTargetSmartPtr;
379 template <class T>
380 inline
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>
396 inline
397 NSCAP_BOOL
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>
405 inline
406 NSCAP_BOOL
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>
416 inline
417 NSCAP_BOOL
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>
424 inline
425 NSCAP_BOOL
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>
432 inline
433 NSCAP_BOOL
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>
440 inline
441 NSCAP_BOOL
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>
456 inline
457 NSCAP_BOOL
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>
464 inline
465 NSCAP_BOOL
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>
472 inline
473 NSCAP_BOOL
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>
480 inline
481 NSCAP_BOOL
482 operator!=( U* lhs, const nsHtml5RefPtr<T>& rhs )
484 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
486 #endif
490 // Comparing an |nsHtml5RefPtr| to |0|
492 template <class T>
493 inline
494 NSCAP_BOOL
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);
501 template <class T>
502 inline
503 NSCAP_BOOL
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());
510 template <class T>
511 inline
512 NSCAP_BOOL
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);
519 template <class T>
520 inline
521 NSCAP_BOOL
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.
534 template <class T>
535 inline
536 NSCAP_BOOL
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);
543 template <class T>
544 inline
545 NSCAP_BOOL
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___)