/src/mozilla-central/xpcom/base/nsISupportsUtils.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef nsISupportsUtils_h__ |
8 | | #define nsISupportsUtils_h__ |
9 | | |
10 | | #include "nscore.h" |
11 | | #include "nsISupportsBase.h" |
12 | | #include "nsError.h" |
13 | | #include "nsDebug.h" |
14 | | #include "nsISupportsImpl.h" |
15 | | #include "mozilla/RefPtr.h" |
16 | | #include "mozilla/TypeTraits.h" |
17 | | |
18 | | /** |
19 | | * Macro for adding a reference to an interface. |
20 | | * @param _ptr The interface pointer. |
21 | | */ |
22 | | #define NS_ADDREF(_ptr) \ |
23 | 12.8M | (_ptr)->AddRef() |
24 | | |
25 | | /** |
26 | | * Macro for adding a reference to this. This macro should be used |
27 | | * because NS_ADDREF (when tracing) may require an ambiguous cast |
28 | | * from the pointers primary type to nsISupports. This macro sidesteps |
29 | | * that entire problem. |
30 | | */ |
31 | | #define NS_ADDREF_THIS() \ |
32 | | AddRef() |
33 | | |
34 | | |
35 | | // Making this a |inline| |template| allows |aExpr| to be evaluated only once, |
36 | | // yet still denies you the ability to |AddRef()| an |nsCOMPtr|. |
37 | | template<class T> |
38 | | inline void |
39 | | ns_if_addref(T aExpr) |
40 | 3 | { |
41 | 3 | if (aExpr) { |
42 | 3 | aExpr->AddRef(); |
43 | 3 | } |
44 | 3 | } |
45 | | |
46 | | /** |
47 | | * Macro for adding a reference to an interface that checks for nullptr. |
48 | | * @param _expr The interface pointer. |
49 | | */ |
50 | 0 | #define NS_IF_ADDREF(_expr) ns_if_addref(_expr) |
51 | | |
52 | | /* |
53 | | * Given these declarations, it explicitly OK and efficient to end a `getter' with: |
54 | | * |
55 | | * NS_IF_ADDREF(*result = mThing); |
56 | | * |
57 | | * even if |mThing| is an |nsCOMPtr|. If |mThing| is an |nsCOMPtr|, however, it is still |
58 | | * _illegal_ to say |NS_IF_ADDREF(mThing)|. |
59 | | */ |
60 | | |
61 | | /** |
62 | | * Macro for releasing a reference to an interface. |
63 | | * @param _ptr The interface pointer. |
64 | | */ |
65 | | #define NS_RELEASE(_ptr) \ |
66 | 0 | do { \ |
67 | 0 | (_ptr)->Release(); \ |
68 | 0 | (_ptr) = 0; \ |
69 | 0 | } while (0) |
70 | | |
71 | | /** |
72 | | * Macro for releasing a reference to this interface. |
73 | | */ |
74 | | #define NS_RELEASE_THIS() \ |
75 | | Release() |
76 | | |
77 | | /** |
78 | | * Macro for releasing a reference to an interface, except that this |
79 | | * macro preserves the return value from the underlying Release call. |
80 | | * The interface pointer argument will only be NULLed if the reference count |
81 | | * goes to zero. |
82 | | * |
83 | | * @param _ptr The interface pointer. |
84 | | * @param _rc The reference count. |
85 | | */ |
86 | | #define NS_RELEASE2(_ptr, _rc) \ |
87 | | do { \ |
88 | | _rc = (_ptr)->Release(); \ |
89 | | if (0 == (_rc)) (_ptr) = 0; \ |
90 | | } while (0) |
91 | | |
92 | | /** |
93 | | * Macro for releasing a reference to an interface that checks for nullptr; |
94 | | * @param _ptr The interface pointer. |
95 | | */ |
96 | | #define NS_IF_RELEASE(_ptr) \ |
97 | 0 | do { \ |
98 | 0 | if (_ptr) { \ |
99 | 0 | (_ptr)->Release(); \ |
100 | 0 | (_ptr) = 0; \ |
101 | 0 | } \ |
102 | 0 | } while (0) |
103 | | |
104 | | /* |
105 | | * Often you have to cast an implementation pointer, e.g., |this|, to an |
106 | | * |nsISupports*|, but because you have multiple inheritance, a simple cast |
107 | | * is ambiguous. One could simply say, e.g., (given a base |nsIBase|), |
108 | | * |static_cast<nsIBase*>(this)|; but that disguises the fact that what |
109 | | * you are really doing is disambiguating the |nsISupports|. You could make |
110 | | * that more obvious with a double cast, e.g., |static_cast<nsISupports*> |
111 | | (* static_cast<nsIBase*>(this))|, but that is bulky and harder to read... |
112 | | * |
113 | | * The following macro is clean, short, and obvious. In the example above, |
114 | | * you would use it like this: |NS_ISUPPORTS_CAST(nsIBase*, this)|. |
115 | | */ |
116 | | |
117 | | #define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \ |
118 | 0 | static_cast<nsISupports*>(static_cast<__unambiguousBase>(__expr)) |
119 | | |
120 | | // a type-safe shortcut for calling the |QueryInterface()| member function |
121 | | template<class T, class DestinationType> |
122 | | inline nsresult |
123 | | CallQueryInterface(T* aSource, DestinationType** aDestination) |
124 | 0 | { |
125 | 0 | // We permit nsISupports-to-nsISupports here so that one can still obtain |
126 | 0 | // the canonical nsISupports pointer with CallQueryInterface. |
127 | 0 | static_assert(!mozilla::IsSame<T, DestinationType>::value || |
128 | 0 | mozilla::IsSame<DestinationType, nsISupports>::value, |
129 | 0 | "don't use CallQueryInterface for compile-time-determinable casts"); |
130 | 0 |
|
131 | 0 | MOZ_ASSERT(aSource, "null parameter"); |
132 | 0 | MOZ_ASSERT(aDestination, "null parameter"); |
133 | 0 |
|
134 | 0 | return aSource->QueryInterface(NS_GET_TEMPLATE_IID(DestinationType), |
135 | 0 | reinterpret_cast<void**>(aDestination)); |
136 | 0 | } |
137 | | |
138 | | template <class SourceType, class DestinationType> |
139 | | inline nsresult |
140 | | CallQueryInterface(RefPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr) |
141 | | { |
142 | | return CallQueryInterface(aSourcePtr.get(), aDestPtr); |
143 | | } |
144 | | |
145 | | #endif /* __nsISupportsUtils_h */ |