Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef nsHtml5RefPtr_h
7 #define nsHtml5RefPtr_h
9 #include "nsThreadUtils.h"
11 template <class T>
12 class nsHtml5RefPtrReleaser : public nsRunnable
13 {
14 private:
15 T* mPtr;
16 public:
17 nsHtml5RefPtrReleaser(T* aPtr)
18 : mPtr(aPtr)
19 {}
20 NS_IMETHODIMP Run()
21 {
22 mPtr->Release();
23 return NS_OK;
24 }
25 };
27 // template <class T> class nsHtml5RefPtrGetterAddRefs;
29 /**
30 * Like nsRefPtr except release is proxied to the main thread. Mostly copied
31 * from nsRefPtr.
32 */
33 template <class T>
34 class nsHtml5RefPtr
35 {
36 private:
38 void
39 assign_with_AddRef( T* rawPtr )
40 {
41 if ( rawPtr )
42 rawPtr->AddRef();
43 assign_assuming_AddRef(rawPtr);
44 }
46 void**
47 begin_assignment()
48 {
49 assign_assuming_AddRef(0);
50 return reinterpret_cast<void**>(&mRawPtr);
51 }
53 void
54 assign_assuming_AddRef( T* newPtr )
55 {
56 T* oldPtr = mRawPtr;
57 mRawPtr = newPtr;
58 if ( oldPtr )
59 release(oldPtr);
60 }
62 void
63 release( T* aPtr )
64 {
65 nsCOMPtr<nsIRunnable> releaser = new nsHtml5RefPtrReleaser<T>(aPtr);
66 if (NS_FAILED(NS_DispatchToMainThread(releaser)))
67 {
68 NS_WARNING("Failed to dispatch releaser event.");
69 }
70 }
72 private:
73 T* mRawPtr;
75 public:
76 typedef T element_type;
78 ~nsHtml5RefPtr()
79 {
80 if ( mRawPtr )
81 release(mRawPtr);
82 }
84 // Constructors
86 nsHtml5RefPtr()
87 : mRawPtr(0)
88 // default constructor
89 {
90 }
92 nsHtml5RefPtr( const nsHtml5RefPtr<T>& aSmartPtr )
93 : mRawPtr(aSmartPtr.mRawPtr)
94 // copy-constructor
95 {
96 if ( mRawPtr )
97 mRawPtr->AddRef();
98 }
100 nsHtml5RefPtr( T* aRawPtr )
101 : mRawPtr(aRawPtr)
102 // construct from a raw pointer (of the right type)
103 {
104 if ( mRawPtr )
105 mRawPtr->AddRef();
106 }
108 nsHtml5RefPtr( const already_AddRefed<T>& aSmartPtr )
109 : mRawPtr(aSmartPtr.mRawPtr)
110 // construct from |dont_AddRef(expr)|
111 {
112 }
114 // Assignment operators
116 nsHtml5RefPtr<T>&
117 operator=( const nsHtml5RefPtr<T>& rhs )
118 // copy assignment operator
119 {
120 assign_with_AddRef(rhs.mRawPtr);
121 return *this;
122 }
124 nsHtml5RefPtr<T>&
125 operator=( T* rhs )
126 // assign from a raw pointer (of the right type)
127 {
128 assign_with_AddRef(rhs);
129 return *this;
130 }
132 nsHtml5RefPtr<T>&
133 operator=( const already_AddRefed<T>& rhs )
134 // assign from |dont_AddRef(expr)|
135 {
136 assign_assuming_AddRef(rhs.mRawPtr);
137 return *this;
138 }
140 // Other pointer operators
142 void
143 swap( nsHtml5RefPtr<T>& rhs )
144 // ...exchange ownership with |rhs|; can save a pair of refcount operations
145 {
146 T* temp = rhs.mRawPtr;
147 rhs.mRawPtr = mRawPtr;
148 mRawPtr = temp;
149 }
151 void
152 swap( T*& rhs )
153 // ...exchange ownership with |rhs|; can save a pair of refcount operations
154 {
155 T* temp = rhs;
156 rhs = mRawPtr;
157 mRawPtr = temp;
158 }
160 already_AddRefed<T>
161 forget()
162 // return the value of mRawPtr and null out mRawPtr. Useful for
163 // already_AddRefed return values.
164 {
165 T* temp = 0;
166 swap(temp);
167 return temp;
168 }
170 template <typename I>
171 void
172 forget( I** rhs)
173 // Set the target of rhs to the value of mRawPtr and null out mRawPtr.
174 // Useful to avoid unnecessary AddRef/Release pairs with "out"
175 // parameters where rhs bay be a T** or an I** where I is a base class
176 // of T.
177 {
178 NS_ASSERTION(rhs, "Null pointer passed to forget!");
179 *rhs = mRawPtr;
180 mRawPtr = 0;
181 }
183 T*
184 get() const
185 /*
186 Prefer the implicit conversion provided automatically by |operator T*() const|.
187 Use |get()| to resolve ambiguity or to get a castable pointer.
188 */
189 {
190 return const_cast<T*>(mRawPtr);
191 }
193 operator T*() const
194 /*
195 ...makes an |nsHtml5RefPtr| act like its underlying raw pointer type whenever it
196 is used in a context where a raw pointer is expected. It is this operator
197 that makes an |nsHtml5RefPtr| substitutable for a raw pointer.
199 Prefer the implicit use of this operator to calling |get()|, except where
200 necessary to resolve ambiguity.
201 */
202 {
203 return get();
204 }
206 T*
207 operator->() const
208 {
209 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsHtml5RefPtr with operator->().");
210 return get();
211 }
213 nsHtml5RefPtr<T>*
214 get_address()
215 // This is not intended to be used by clients. See |address_of|
216 // below.
217 {
218 return this;
219 }
221 const nsHtml5RefPtr<T>*
222 get_address() const
223 // This is not intended to be used by clients. See |address_of|
224 // below.
225 {
226 return this;
227 }
229 public:
230 T&
231 operator*() const
232 {
233 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsHtml5RefPtr with operator*().");
234 return *get();
235 }
237 T**
238 StartAssignment()
239 {
240 #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
241 return reinterpret_cast<T**>(begin_assignment());
242 #else
243 assign_assuming_AddRef(0);
244 return reinterpret_cast<T**>(&mRawPtr);
245 #endif
246 }
247 };
249 template <class T>
250 inline
251 nsHtml5RefPtr<T>*
252 address_of( nsHtml5RefPtr<T>& aPtr )
253 {
254 return aPtr.get_address();
255 }
257 template <class T>
258 inline
259 const nsHtml5RefPtr<T>*
260 address_of( const nsHtml5RefPtr<T>& aPtr )
261 {
262 return aPtr.get_address();
263 }
265 template <class T>
266 class nsHtml5RefPtrGetterAddRefs
267 /*
268 ...
270 This class is designed to be used for anonymous temporary objects in the
271 argument list of calls that return COM interface pointers, e.g.,
273 nsHtml5RefPtr<IFoo> fooP;
274 ...->GetAddRefedPointer(getter_AddRefs(fooP))
276 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
278 When initialized with a |nsHtml5RefPtr|, as in the example above, it returns
279 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
280 outer call (|GetAddRefedPointer| in this case) can fill in.
282 This type should be a nested class inside |nsHtml5RefPtr<T>|.
283 */
284 {
285 public:
286 explicit
287 nsHtml5RefPtrGetterAddRefs( nsHtml5RefPtr<T>& aSmartPtr )
288 : mTargetSmartPtr(aSmartPtr)
289 {
290 // nothing else to do
291 }
293 operator void**()
294 {
295 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
296 }
298 operator T**()
299 {
300 return mTargetSmartPtr.StartAssignment();
301 }
303 T*&
304 operator*()
305 {
306 return *(mTargetSmartPtr.StartAssignment());
307 }
309 private:
310 nsHtml5RefPtr<T>& mTargetSmartPtr;
311 };
313 template <class T>
314 inline
315 nsHtml5RefPtrGetterAddRefs<T>
316 getter_AddRefs( nsHtml5RefPtr<T>& aSmartPtr )
317 /*
318 Used around a |nsHtml5RefPtr| when
319 ...makes the class |nsHtml5RefPtrGetterAddRefs<T>| invisible.
320 */
321 {
322 return nsHtml5RefPtrGetterAddRefs<T>(aSmartPtr);
323 }
327 // Comparing two |nsHtml5RefPtr|s
329 template <class T, class U>
330 inline
331 bool
332 operator==( const nsHtml5RefPtr<T>& lhs, const nsHtml5RefPtr<U>& rhs )
333 {
334 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get());
335 }
338 template <class T, class U>
339 inline
340 bool
341 operator!=( const nsHtml5RefPtr<T>& lhs, const nsHtml5RefPtr<U>& rhs )
342 {
343 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get());
344 }
347 // Comparing an |nsHtml5RefPtr| to a raw pointer
349 template <class T, class U>
350 inline
351 bool
352 operator==( const nsHtml5RefPtr<T>& lhs, const U* rhs )
353 {
354 return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs);
355 }
357 template <class T, class U>
358 inline
359 bool
360 operator==( const U* lhs, const nsHtml5RefPtr<T>& rhs )
361 {
362 return static_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
363 }
365 template <class T, class U>
366 inline
367 bool
368 operator!=( const nsHtml5RefPtr<T>& lhs, const U* rhs )
369 {
370 return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs);
371 }
373 template <class T, class U>
374 inline
375 bool
376 operator!=( const U* lhs, const nsHtml5RefPtr<T>& rhs )
377 {
378 return static_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
379 }
381 // To avoid ambiguities caused by the presence of builtin |operator==|s
382 // creating a situation where one of the |operator==| defined above
383 // has a better conversion for one argument and the builtin has a
384 // better conversion for the other argument, define additional
385 // |operator==| without the |const| on the raw pointer.
386 // See bug 65664 for details.
388 #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
389 template <class T, class U>
390 inline
391 bool
392 operator==( const nsHtml5RefPtr<T>& lhs, U* rhs )
393 {
394 return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs);
395 }
397 template <class T, class U>
398 inline
399 bool
400 operator==( U* lhs, const nsHtml5RefPtr<T>& rhs )
401 {
402 return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get());
403 }
405 template <class T, class U>
406 inline
407 bool
408 operator!=( const nsHtml5RefPtr<T>& lhs, U* rhs )
409 {
410 return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs);
411 }
413 template <class T, class U>
414 inline
415 bool
416 operator!=( U* lhs, const nsHtml5RefPtr<T>& rhs )
417 {
418 return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get());
419 }
420 #endif
424 // Comparing an |nsHtml5RefPtr| to |0|
426 template <class T>
427 inline
428 bool
429 operator==( const nsHtml5RefPtr<T>& lhs, NSCAP_Zero* rhs )
430 // specifically to allow |smartPtr == 0|
431 {
432 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
433 }
435 template <class T>
436 inline
437 bool
438 operator==( NSCAP_Zero* lhs, const nsHtml5RefPtr<T>& rhs )
439 // specifically to allow |0 == smartPtr|
440 {
441 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
442 }
444 template <class T>
445 inline
446 bool
447 operator!=( const nsHtml5RefPtr<T>& lhs, NSCAP_Zero* rhs )
448 // specifically to allow |smartPtr != 0|
449 {
450 return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs);
451 }
453 template <class T>
454 inline
455 bool
456 operator!=( NSCAP_Zero* lhs, const nsHtml5RefPtr<T>& rhs )
457 // specifically to allow |0 != smartPtr|
458 {
459 return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get());
460 }
463 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
465 // We need to explicitly define comparison operators for `int'
466 // because the compiler is lame.
468 template <class T>
469 inline
470 bool
471 operator==( const nsHtml5RefPtr<T>& lhs, int rhs )
472 // specifically to allow |smartPtr == 0|
473 {
474 return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs);
475 }
477 template <class T>
478 inline
479 bool
480 operator==( int lhs, const nsHtml5RefPtr<T>& rhs )
481 // specifically to allow |0 == smartPtr|
482 {
483 return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get());
484 }
486 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
488 #endif // !defined(nsHtml5RefPtr_h)