1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/parser/html/nsHtml5RefPtr.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,488 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsHtml5RefPtr_h 1.10 +#define nsHtml5RefPtr_h 1.11 + 1.12 +#include "nsThreadUtils.h" 1.13 + 1.14 +template <class T> 1.15 +class nsHtml5RefPtrReleaser : public nsRunnable 1.16 + { 1.17 + private: 1.18 + T* mPtr; 1.19 + public: 1.20 + nsHtml5RefPtrReleaser(T* aPtr) 1.21 + : mPtr(aPtr) 1.22 + {} 1.23 + NS_IMETHODIMP Run() 1.24 + { 1.25 + mPtr->Release(); 1.26 + return NS_OK; 1.27 + } 1.28 + }; 1.29 + 1.30 +// template <class T> class nsHtml5RefPtrGetterAddRefs; 1.31 + 1.32 +/** 1.33 + * Like nsRefPtr except release is proxied to the main thread. Mostly copied 1.34 + * from nsRefPtr. 1.35 + */ 1.36 +template <class T> 1.37 +class nsHtml5RefPtr 1.38 + { 1.39 + private: 1.40 + 1.41 + void 1.42 + assign_with_AddRef( T* rawPtr ) 1.43 + { 1.44 + if ( rawPtr ) 1.45 + rawPtr->AddRef(); 1.46 + assign_assuming_AddRef(rawPtr); 1.47 + } 1.48 + 1.49 + void** 1.50 + begin_assignment() 1.51 + { 1.52 + assign_assuming_AddRef(0); 1.53 + return reinterpret_cast<void**>(&mRawPtr); 1.54 + } 1.55 + 1.56 + void 1.57 + assign_assuming_AddRef( T* newPtr ) 1.58 + { 1.59 + T* oldPtr = mRawPtr; 1.60 + mRawPtr = newPtr; 1.61 + if ( oldPtr ) 1.62 + release(oldPtr); 1.63 + } 1.64 + 1.65 + void 1.66 + release( T* aPtr ) 1.67 + { 1.68 + nsCOMPtr<nsIRunnable> releaser = new nsHtml5RefPtrReleaser<T>(aPtr); 1.69 + if (NS_FAILED(NS_DispatchToMainThread(releaser))) 1.70 + { 1.71 + NS_WARNING("Failed to dispatch releaser event."); 1.72 + } 1.73 + } 1.74 + 1.75 + private: 1.76 + T* mRawPtr; 1.77 + 1.78 + public: 1.79 + typedef T element_type; 1.80 + 1.81 + ~nsHtml5RefPtr() 1.82 + { 1.83 + if ( mRawPtr ) 1.84 + release(mRawPtr); 1.85 + } 1.86 + 1.87 + // Constructors 1.88 + 1.89 + nsHtml5RefPtr() 1.90 + : mRawPtr(0) 1.91 + // default constructor 1.92 + { 1.93 + } 1.94 + 1.95 + nsHtml5RefPtr( const nsHtml5RefPtr<T>& aSmartPtr ) 1.96 + : mRawPtr(aSmartPtr.mRawPtr) 1.97 + // copy-constructor 1.98 + { 1.99 + if ( mRawPtr ) 1.100 + mRawPtr->AddRef(); 1.101 + } 1.102 + 1.103 + nsHtml5RefPtr( T* aRawPtr ) 1.104 + : mRawPtr(aRawPtr) 1.105 + // construct from a raw pointer (of the right type) 1.106 + { 1.107 + if ( mRawPtr ) 1.108 + mRawPtr->AddRef(); 1.109 + } 1.110 + 1.111 + nsHtml5RefPtr( const already_AddRefed<T>& aSmartPtr ) 1.112 + : mRawPtr(aSmartPtr.mRawPtr) 1.113 + // construct from |dont_AddRef(expr)| 1.114 + { 1.115 + } 1.116 + 1.117 + // Assignment operators 1.118 + 1.119 + nsHtml5RefPtr<T>& 1.120 + operator=( const nsHtml5RefPtr<T>& rhs ) 1.121 + // copy assignment operator 1.122 + { 1.123 + assign_with_AddRef(rhs.mRawPtr); 1.124 + return *this; 1.125 + } 1.126 + 1.127 + nsHtml5RefPtr<T>& 1.128 + operator=( T* rhs ) 1.129 + // assign from a raw pointer (of the right type) 1.130 + { 1.131 + assign_with_AddRef(rhs); 1.132 + return *this; 1.133 + } 1.134 + 1.135 + nsHtml5RefPtr<T>& 1.136 + operator=( const already_AddRefed<T>& rhs ) 1.137 + // assign from |dont_AddRef(expr)| 1.138 + { 1.139 + assign_assuming_AddRef(rhs.mRawPtr); 1.140 + return *this; 1.141 + } 1.142 + 1.143 + // Other pointer operators 1.144 + 1.145 + void 1.146 + swap( nsHtml5RefPtr<T>& rhs ) 1.147 + // ...exchange ownership with |rhs|; can save a pair of refcount operations 1.148 + { 1.149 + T* temp = rhs.mRawPtr; 1.150 + rhs.mRawPtr = mRawPtr; 1.151 + mRawPtr = temp; 1.152 + } 1.153 + 1.154 + void 1.155 + swap( T*& rhs ) 1.156 + // ...exchange ownership with |rhs|; can save a pair of refcount operations 1.157 + { 1.158 + T* temp = rhs; 1.159 + rhs = mRawPtr; 1.160 + mRawPtr = temp; 1.161 + } 1.162 + 1.163 + already_AddRefed<T> 1.164 + forget() 1.165 + // return the value of mRawPtr and null out mRawPtr. Useful for 1.166 + // already_AddRefed return values. 1.167 + { 1.168 + T* temp = 0; 1.169 + swap(temp); 1.170 + return temp; 1.171 + } 1.172 + 1.173 + template <typename I> 1.174 + void 1.175 + forget( I** rhs) 1.176 + // Set the target of rhs to the value of mRawPtr and null out mRawPtr. 1.177 + // Useful to avoid unnecessary AddRef/Release pairs with "out" 1.178 + // parameters where rhs bay be a T** or an I** where I is a base class 1.179 + // of T. 1.180 + { 1.181 + NS_ASSERTION(rhs, "Null pointer passed to forget!"); 1.182 + *rhs = mRawPtr; 1.183 + mRawPtr = 0; 1.184 + } 1.185 + 1.186 + T* 1.187 + get() const 1.188 + /* 1.189 + Prefer the implicit conversion provided automatically by |operator T*() const|. 1.190 + Use |get()| to resolve ambiguity or to get a castable pointer. 1.191 + */ 1.192 + { 1.193 + return const_cast<T*>(mRawPtr); 1.194 + } 1.195 + 1.196 + operator T*() const 1.197 + /* 1.198 + ...makes an |nsHtml5RefPtr| act like its underlying raw pointer type whenever it 1.199 + is used in a context where a raw pointer is expected. It is this operator 1.200 + that makes an |nsHtml5RefPtr| substitutable for a raw pointer. 1.201 + 1.202 + Prefer the implicit use of this operator to calling |get()|, except where 1.203 + necessary to resolve ambiguity. 1.204 + */ 1.205 + { 1.206 + return get(); 1.207 + } 1.208 + 1.209 + T* 1.210 + operator->() const 1.211 + { 1.212 + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsHtml5RefPtr with operator->()."); 1.213 + return get(); 1.214 + } 1.215 + 1.216 + nsHtml5RefPtr<T>* 1.217 + get_address() 1.218 + // This is not intended to be used by clients. See |address_of| 1.219 + // below. 1.220 + { 1.221 + return this; 1.222 + } 1.223 + 1.224 + const nsHtml5RefPtr<T>* 1.225 + get_address() const 1.226 + // This is not intended to be used by clients. See |address_of| 1.227 + // below. 1.228 + { 1.229 + return this; 1.230 + } 1.231 + 1.232 + public: 1.233 + T& 1.234 + operator*() const 1.235 + { 1.236 + NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsHtml5RefPtr with operator*()."); 1.237 + return *get(); 1.238 + } 1.239 + 1.240 + T** 1.241 + StartAssignment() 1.242 + { 1.243 +#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT 1.244 + return reinterpret_cast<T**>(begin_assignment()); 1.245 +#else 1.246 + assign_assuming_AddRef(0); 1.247 + return reinterpret_cast<T**>(&mRawPtr); 1.248 +#endif 1.249 + } 1.250 + }; 1.251 + 1.252 +template <class T> 1.253 +inline 1.254 +nsHtml5RefPtr<T>* 1.255 +address_of( nsHtml5RefPtr<T>& aPtr ) 1.256 + { 1.257 + return aPtr.get_address(); 1.258 + } 1.259 + 1.260 +template <class T> 1.261 +inline 1.262 +const nsHtml5RefPtr<T>* 1.263 +address_of( const nsHtml5RefPtr<T>& aPtr ) 1.264 + { 1.265 + return aPtr.get_address(); 1.266 + } 1.267 + 1.268 +template <class T> 1.269 +class nsHtml5RefPtrGetterAddRefs 1.270 + /* 1.271 + ... 1.272 + 1.273 + This class is designed to be used for anonymous temporary objects in the 1.274 + argument list of calls that return COM interface pointers, e.g., 1.275 + 1.276 + nsHtml5RefPtr<IFoo> fooP; 1.277 + ...->GetAddRefedPointer(getter_AddRefs(fooP)) 1.278 + 1.279 + DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead. 1.280 + 1.281 + When initialized with a |nsHtml5RefPtr|, as in the example above, it returns 1.282 + a |void**|, a |T**|, or an |nsISupports**| as needed, that the 1.283 + outer call (|GetAddRefedPointer| in this case) can fill in. 1.284 + 1.285 + This type should be a nested class inside |nsHtml5RefPtr<T>|. 1.286 + */ 1.287 + { 1.288 + public: 1.289 + explicit 1.290 + nsHtml5RefPtrGetterAddRefs( nsHtml5RefPtr<T>& aSmartPtr ) 1.291 + : mTargetSmartPtr(aSmartPtr) 1.292 + { 1.293 + // nothing else to do 1.294 + } 1.295 + 1.296 + operator void**() 1.297 + { 1.298 + return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment()); 1.299 + } 1.300 + 1.301 + operator T**() 1.302 + { 1.303 + return mTargetSmartPtr.StartAssignment(); 1.304 + } 1.305 + 1.306 + T*& 1.307 + operator*() 1.308 + { 1.309 + return *(mTargetSmartPtr.StartAssignment()); 1.310 + } 1.311 + 1.312 + private: 1.313 + nsHtml5RefPtr<T>& mTargetSmartPtr; 1.314 + }; 1.315 + 1.316 +template <class T> 1.317 +inline 1.318 +nsHtml5RefPtrGetterAddRefs<T> 1.319 +getter_AddRefs( nsHtml5RefPtr<T>& aSmartPtr ) 1.320 + /* 1.321 + Used around a |nsHtml5RefPtr| when 1.322 + ...makes the class |nsHtml5RefPtrGetterAddRefs<T>| invisible. 1.323 + */ 1.324 + { 1.325 + return nsHtml5RefPtrGetterAddRefs<T>(aSmartPtr); 1.326 + } 1.327 + 1.328 + 1.329 + 1.330 + // Comparing two |nsHtml5RefPtr|s 1.331 + 1.332 +template <class T, class U> 1.333 +inline 1.334 +bool 1.335 +operator==( const nsHtml5RefPtr<T>& lhs, const nsHtml5RefPtr<U>& rhs ) 1.336 + { 1.337 + return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs.get()); 1.338 + } 1.339 + 1.340 + 1.341 +template <class T, class U> 1.342 +inline 1.343 +bool 1.344 +operator!=( const nsHtml5RefPtr<T>& lhs, const nsHtml5RefPtr<U>& rhs ) 1.345 + { 1.346 + return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs.get()); 1.347 + } 1.348 + 1.349 + 1.350 + // Comparing an |nsHtml5RefPtr| to a raw pointer 1.351 + 1.352 +template <class T, class U> 1.353 +inline 1.354 +bool 1.355 +operator==( const nsHtml5RefPtr<T>& lhs, const U* rhs ) 1.356 + { 1.357 + return static_cast<const T*>(lhs.get()) == static_cast<const U*>(rhs); 1.358 + } 1.359 + 1.360 +template <class T, class U> 1.361 +inline 1.362 +bool 1.363 +operator==( const U* lhs, const nsHtml5RefPtr<T>& rhs ) 1.364 + { 1.365 + return static_cast<const U*>(lhs) == static_cast<const T*>(rhs.get()); 1.366 + } 1.367 + 1.368 +template <class T, class U> 1.369 +inline 1.370 +bool 1.371 +operator!=( const nsHtml5RefPtr<T>& lhs, const U* rhs ) 1.372 + { 1.373 + return static_cast<const T*>(lhs.get()) != static_cast<const U*>(rhs); 1.374 + } 1.375 + 1.376 +template <class T, class U> 1.377 +inline 1.378 +bool 1.379 +operator!=( const U* lhs, const nsHtml5RefPtr<T>& rhs ) 1.380 + { 1.381 + return static_cast<const U*>(lhs) != static_cast<const T*>(rhs.get()); 1.382 + } 1.383 + 1.384 + // To avoid ambiguities caused by the presence of builtin |operator==|s 1.385 + // creating a situation where one of the |operator==| defined above 1.386 + // has a better conversion for one argument and the builtin has a 1.387 + // better conversion for the other argument, define additional 1.388 + // |operator==| without the |const| on the raw pointer. 1.389 + // See bug 65664 for details. 1.390 + 1.391 +#ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ 1.392 +template <class T, class U> 1.393 +inline 1.394 +bool 1.395 +operator==( const nsHtml5RefPtr<T>& lhs, U* rhs ) 1.396 + { 1.397 + return static_cast<const T*>(lhs.get()) == const_cast<const U*>(rhs); 1.398 + } 1.399 + 1.400 +template <class T, class U> 1.401 +inline 1.402 +bool 1.403 +operator==( U* lhs, const nsHtml5RefPtr<T>& rhs ) 1.404 + { 1.405 + return const_cast<const U*>(lhs) == static_cast<const T*>(rhs.get()); 1.406 + } 1.407 + 1.408 +template <class T, class U> 1.409 +inline 1.410 +bool 1.411 +operator!=( const nsHtml5RefPtr<T>& lhs, U* rhs ) 1.412 + { 1.413 + return static_cast<const T*>(lhs.get()) != const_cast<const U*>(rhs); 1.414 + } 1.415 + 1.416 +template <class T, class U> 1.417 +inline 1.418 +bool 1.419 +operator!=( U* lhs, const nsHtml5RefPtr<T>& rhs ) 1.420 + { 1.421 + return const_cast<const U*>(lhs) != static_cast<const T*>(rhs.get()); 1.422 + } 1.423 +#endif 1.424 + 1.425 + 1.426 + 1.427 + // Comparing an |nsHtml5RefPtr| to |0| 1.428 + 1.429 +template <class T> 1.430 +inline 1.431 +bool 1.432 +operator==( const nsHtml5RefPtr<T>& lhs, NSCAP_Zero* rhs ) 1.433 + // specifically to allow |smartPtr == 0| 1.434 + { 1.435 + return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs); 1.436 + } 1.437 + 1.438 +template <class T> 1.439 +inline 1.440 +bool 1.441 +operator==( NSCAP_Zero* lhs, const nsHtml5RefPtr<T>& rhs ) 1.442 + // specifically to allow |0 == smartPtr| 1.443 + { 1.444 + return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get()); 1.445 + } 1.446 + 1.447 +template <class T> 1.448 +inline 1.449 +bool 1.450 +operator!=( const nsHtml5RefPtr<T>& lhs, NSCAP_Zero* rhs ) 1.451 + // specifically to allow |smartPtr != 0| 1.452 + { 1.453 + return static_cast<const void*>(lhs.get()) != reinterpret_cast<const void*>(rhs); 1.454 + } 1.455 + 1.456 +template <class T> 1.457 +inline 1.458 +bool 1.459 +operator!=( NSCAP_Zero* lhs, const nsHtml5RefPtr<T>& rhs ) 1.460 + // specifically to allow |0 != smartPtr| 1.461 + { 1.462 + return reinterpret_cast<const void*>(lhs) != static_cast<const void*>(rhs.get()); 1.463 + } 1.464 + 1.465 + 1.466 +#ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO 1.467 + 1.468 + // We need to explicitly define comparison operators for `int' 1.469 + // because the compiler is lame. 1.470 + 1.471 +template <class T> 1.472 +inline 1.473 +bool 1.474 +operator==( const nsHtml5RefPtr<T>& lhs, int rhs ) 1.475 + // specifically to allow |smartPtr == 0| 1.476 + { 1.477 + return static_cast<const void*>(lhs.get()) == reinterpret_cast<const void*>(rhs); 1.478 + } 1.479 + 1.480 +template <class T> 1.481 +inline 1.482 +bool 1.483 +operator==( int lhs, const nsHtml5RefPtr<T>& rhs ) 1.484 + // specifically to allow |0 == smartPtr| 1.485 + { 1.486 + return reinterpret_cast<const void*>(lhs) == static_cast<const void*>(rhs.get()); 1.487 + } 1.488 + 1.489 +#endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO) 1.490 + 1.491 +#endif // !defined(nsHtml5RefPtr_h)