parser/html/nsHtml5RefPtr.h

branch
TOR_BUG_9701
changeset 14
925c144e1f1f
equal deleted inserted replaced
-1:000000000000 0:ce4a35ebcd56
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/. */
5
6 #ifndef nsHtml5RefPtr_h
7 #define nsHtml5RefPtr_h
8
9 #include "nsThreadUtils.h"
10
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 };
26
27 // template <class T> class nsHtml5RefPtrGetterAddRefs;
28
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:
37
38 void
39 assign_with_AddRef( T* rawPtr )
40 {
41 if ( rawPtr )
42 rawPtr->AddRef();
43 assign_assuming_AddRef(rawPtr);
44 }
45
46 void**
47 begin_assignment()
48 {
49 assign_assuming_AddRef(0);
50 return reinterpret_cast<void**>(&mRawPtr);
51 }
52
53 void
54 assign_assuming_AddRef( T* newPtr )
55 {
56 T* oldPtr = mRawPtr;
57 mRawPtr = newPtr;
58 if ( oldPtr )
59 release(oldPtr);
60 }
61
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 }
71
72 private:
73 T* mRawPtr;
74
75 public:
76 typedef T element_type;
77
78 ~nsHtml5RefPtr()
79 {
80 if ( mRawPtr )
81 release(mRawPtr);
82 }
83
84 // Constructors
85
86 nsHtml5RefPtr()
87 : mRawPtr(0)
88 // default constructor
89 {
90 }
91
92 nsHtml5RefPtr( const nsHtml5RefPtr<T>& aSmartPtr )
93 : mRawPtr(aSmartPtr.mRawPtr)
94 // copy-constructor
95 {
96 if ( mRawPtr )
97 mRawPtr->AddRef();
98 }
99
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 }
107
108 nsHtml5RefPtr( const already_AddRefed<T>& aSmartPtr )
109 : mRawPtr(aSmartPtr.mRawPtr)
110 // construct from |dont_AddRef(expr)|
111 {
112 }
113
114 // Assignment operators
115
116 nsHtml5RefPtr<T>&
117 operator=( const nsHtml5RefPtr<T>& rhs )
118 // copy assignment operator
119 {
120 assign_with_AddRef(rhs.mRawPtr);
121 return *this;
122 }
123
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 }
131
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 }
139
140 // Other pointer operators
141
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 }
150
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 }
159
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 }
169
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 }
182
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 }
192
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.
198
199 Prefer the implicit use of this operator to calling |get()|, except where
200 necessary to resolve ambiguity.
201 */
202 {
203 return get();
204 }
205
206 T*
207 operator->() const
208 {
209 NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsHtml5RefPtr with operator->().");
210 return get();
211 }
212
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 }
220
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 }
228
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 }
236
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 };
248
249 template <class T>
250 inline
251 nsHtml5RefPtr<T>*
252 address_of( nsHtml5RefPtr<T>& aPtr )
253 {
254 return aPtr.get_address();
255 }
256
257 template <class T>
258 inline
259 const nsHtml5RefPtr<T>*
260 address_of( const nsHtml5RefPtr<T>& aPtr )
261 {
262 return aPtr.get_address();
263 }
264
265 template <class T>
266 class nsHtml5RefPtrGetterAddRefs
267 /*
268 ...
269
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.,
272
273 nsHtml5RefPtr<IFoo> fooP;
274 ...->GetAddRefedPointer(getter_AddRefs(fooP))
275
276 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
277
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.
281
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 }
292
293 operator void**()
294 {
295 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
296 }
297
298 operator T**()
299 {
300 return mTargetSmartPtr.StartAssignment();
301 }
302
303 T*&
304 operator*()
305 {
306 return *(mTargetSmartPtr.StartAssignment());
307 }
308
309 private:
310 nsHtml5RefPtr<T>& mTargetSmartPtr;
311 };
312
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 }
324
325
326
327 // Comparing two |nsHtml5RefPtr|s
328
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 }
336
337
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 }
345
346
347 // Comparing an |nsHtml5RefPtr| to a raw pointer
348
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 }
356
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 }
364
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 }
372
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 }
380
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.
387
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 }
396
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 }
404
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 }
412
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
421
422
423
424 // Comparing an |nsHtml5RefPtr| to |0|
425
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 }
434
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 }
443
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 }
452
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 }
461
462
463 #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
464
465 // We need to explicitly define comparison operators for `int'
466 // because the compiler is lame.
467
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 }
476
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 }
485
486 #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
487
488 #endif // !defined(nsHtml5RefPtr_h)

mercurial