1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/nsISupportsUtils.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,145 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 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 nsISupportsUtils_h__ 1.10 +#define nsISupportsUtils_h__ 1.11 + 1.12 +#include "nscore.h" 1.13 +#include "nsISupportsBase.h" 1.14 +#include "nsError.h" 1.15 +#include "nsDebug.h" 1.16 +#include "nsISupportsImpl.h" 1.17 +#include "mozilla/TypeTraits.h" 1.18 + 1.19 +/** 1.20 + * Macro for adding a reference to an interface. 1.21 + * @param _ptr The interface pointer. 1.22 + */ 1.23 +#define NS_ADDREF(_ptr) \ 1.24 + (_ptr)->AddRef() 1.25 + 1.26 +/** 1.27 + * Macro for adding a reference to this. This macro should be used 1.28 + * because NS_ADDREF (when tracing) may require an ambiguous cast 1.29 + * from the pointers primary type to nsISupports. This macro sidesteps 1.30 + * that entire problem. 1.31 + */ 1.32 +#define NS_ADDREF_THIS() \ 1.33 + AddRef() 1.34 + 1.35 + 1.36 +extern "C++" { 1.37 +// ...because some one is accidentally including this file inside 1.38 +// an |extern "C"| 1.39 + 1.40 + 1.41 +// Making this a |inline| |template| allows |expr| to be evaluated only once, 1.42 +// yet still denies you the ability to |AddRef()| an |nsCOMPtr|. 1.43 +template <class T> 1.44 +inline 1.45 +void 1.46 +ns_if_addref( T expr ) 1.47 +{ 1.48 + if (expr) { 1.49 + expr->AddRef(); 1.50 + } 1.51 +} 1.52 + 1.53 +} /* extern "C++" */ 1.54 + 1.55 +/** 1.56 + * Macro for adding a reference to an interface that checks for nullptr. 1.57 + * @param _expr The interface pointer. 1.58 + */ 1.59 +#define NS_IF_ADDREF(_expr) ns_if_addref(_expr) 1.60 + 1.61 +/* 1.62 + * Given these declarations, it explicitly OK and efficient to end a `getter' with: 1.63 + * 1.64 + * NS_IF_ADDREF(*result = mThing); 1.65 + * 1.66 + * even if |mThing| is an |nsCOMPtr|. If |mThing| is an |nsCOMPtr|, however, it is still 1.67 + * _illegal_ to say |NS_IF_ADDREF(mThing)|. 1.68 + */ 1.69 + 1.70 +/** 1.71 + * Macro for releasing a reference to an interface. 1.72 + * @param _ptr The interface pointer. 1.73 + */ 1.74 +#define NS_RELEASE(_ptr) \ 1.75 + do { \ 1.76 + (_ptr)->Release(); \ 1.77 + (_ptr) = 0; \ 1.78 + } while (0) 1.79 + 1.80 +/** 1.81 + * Macro for releasing a reference to this interface. 1.82 + */ 1.83 +#define NS_RELEASE_THIS() \ 1.84 + Release() 1.85 + 1.86 +/** 1.87 + * Macro for releasing a reference to an interface, except that this 1.88 + * macro preserves the return value from the underlying Release call. 1.89 + * The interface pointer argument will only be NULLed if the reference count 1.90 + * goes to zero. 1.91 + * 1.92 + * @param _ptr The interface pointer. 1.93 + * @param _rc The reference count. 1.94 + */ 1.95 +#define NS_RELEASE2(_ptr, _rc) \ 1.96 + do { \ 1.97 + _rc = (_ptr)->Release(); \ 1.98 + if (0 == (_rc)) (_ptr) = 0; \ 1.99 + } while (0) 1.100 + 1.101 +/** 1.102 + * Macro for releasing a reference to an interface that checks for nullptr; 1.103 + * @param _ptr The interface pointer. 1.104 + */ 1.105 +#define NS_IF_RELEASE(_ptr) \ 1.106 + do { \ 1.107 + if (_ptr) { \ 1.108 + (_ptr)->Release(); \ 1.109 + (_ptr) = 0; \ 1.110 + } \ 1.111 + } while (0) 1.112 + 1.113 +/* 1.114 + * Often you have to cast an implementation pointer, e.g., |this|, to an 1.115 + * |nsISupports*|, but because you have multiple inheritance, a simple cast 1.116 + * is ambiguous. One could simply say, e.g., (given a base |nsIBase|), 1.117 + * |static_cast<nsIBase*>(this)|; but that disguises the fact that what 1.118 + * you are really doing is disambiguating the |nsISupports|. You could make 1.119 + * that more obvious with a double cast, e.g., |static_cast<nsISupports*> 1.120 + (* static_cast<nsIBase*>(this))|, but that is bulky and harder to read... 1.121 + * 1.122 + * The following macro is clean, short, and obvious. In the example above, 1.123 + * you would use it like this: |NS_ISUPPORTS_CAST(nsIBase*, this)|. 1.124 + */ 1.125 + 1.126 +#define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \ 1.127 + static_cast<nsISupports*>(static_cast<__unambiguousBase>(__expr)) 1.128 + 1.129 +// a type-safe shortcut for calling the |QueryInterface()| member function 1.130 +template <class T, class DestinationType> 1.131 +inline 1.132 +nsresult 1.133 +CallQueryInterface( T* aSource, DestinationType** aDestination ) 1.134 +{ 1.135 + // We permit nsISupports-to-nsISupports here so that one can still obtain 1.136 + // the canonical nsISupports pointer with CallQueryInterface. 1.137 + static_assert(!mozilla::IsSame<T, DestinationType>::value || 1.138 + mozilla::IsSame<DestinationType, nsISupports>::value, 1.139 + "don't use CallQueryInterface for compile-time-determinable casts"); 1.140 + 1.141 + NS_PRECONDITION(aSource, "null parameter"); 1.142 + NS_PRECONDITION(aDestination, "null parameter"); 1.143 + 1.144 + return aSource->QueryInterface(NS_GET_TEMPLATE_IID(DestinationType), 1.145 + reinterpret_cast<void**>(aDestination)); 1.146 +} 1.147 + 1.148 +#endif /* __nsISupportsUtils_h */