1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/nsISupportsImpl.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1031 @@ 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 +// IWYU pragma: private, include "nsISupports.h" 1.9 + 1.10 + 1.11 +#ifndef nsISupportsImpl_h__ 1.12 +#define nsISupportsImpl_h__ 1.13 + 1.14 +#include "nscore.h" 1.15 +#include "nsISupportsBase.h" 1.16 +#include "nsISupportsUtils.h" 1.17 + 1.18 + 1.19 +#if !defined(XPCOM_GLUE_AVOID_NSPR) 1.20 +#include "prthread.h" /* needed for thread-safety checks */ 1.21 +#endif // !XPCOM_GLUE_AVOID_NSPR 1.22 + 1.23 +#include "nsDebug.h" 1.24 +#include "nsXPCOM.h" 1.25 +#ifndef XPCOM_GLUE 1.26 +#include "mozilla/Atomics.h" 1.27 +#endif 1.28 +#include "mozilla/Attributes.h" 1.29 +#include "mozilla/Assertions.h" 1.30 +#include "mozilla/Likely.h" 1.31 +#include "mozilla/MacroArgs.h" 1.32 +#include "mozilla/MacroForEach.h" 1.33 + 1.34 +inline nsISupports* 1.35 +ToSupports(nsISupports* p) 1.36 +{ 1.37 + return p; 1.38 +} 1.39 + 1.40 +inline nsISupports* 1.41 +ToCanonicalSupports(nsISupports* p) 1.42 +{ 1.43 + return nullptr; 1.44 +} 1.45 + 1.46 +//////////////////////////////////////////////////////////////////////////////// 1.47 +// Macros to help detect thread-safety: 1.48 + 1.49 +#if (defined(DEBUG) || (defined(NIGHTLY_BUILD) && !defined(MOZ_PROFILING))) && !defined(XPCOM_GLUE_AVOID_NSPR) 1.50 + 1.51 +class nsAutoOwningThread { 1.52 +public: 1.53 + nsAutoOwningThread() { mThread = PR_GetCurrentThread(); } 1.54 + void *GetThread() const { return mThread; } 1.55 + 1.56 +private: 1.57 + void *mThread; 1.58 +}; 1.59 + 1.60 +#define NS_DECL_OWNINGTHREAD nsAutoOwningThread _mOwningThread; 1.61 +#define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) \ 1.62 + NS_CheckThreadSafe(agg->_mOwningThread.GetThread(), #_class " not thread-safe") 1.63 +#define NS_ASSERT_OWNINGTHREAD(_class) NS_ASSERT_OWNINGTHREAD_AGGREGATE(this, _class) 1.64 +#else // !DEBUG && !(NIGHTLY_BUILD && !MOZ_PROFILING) 1.65 + 1.66 +#define NS_DECL_OWNINGTHREAD /* nothing */ 1.67 +#define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) ((void)0) 1.68 +#define NS_ASSERT_OWNINGTHREAD(_class) ((void)0) 1.69 + 1.70 +#endif // DEBUG || (NIGHTLY_BUILD && !MOZ_PROFILING) 1.71 + 1.72 + 1.73 +// Macros for reference-count and constructor logging 1.74 + 1.75 +#ifdef NS_BUILD_REFCNT_LOGGING 1.76 + 1.77 +#define NS_LOG_ADDREF(_p, _rc, _type, _size) \ 1.78 + NS_LogAddRef((_p), (_rc), (_type), (uint32_t) (_size)) 1.79 + 1.80 +#define NS_LOG_RELEASE(_p, _rc, _type) \ 1.81 + NS_LogRelease((_p), (_rc), (_type)) 1.82 + 1.83 +// Note that the following constructor/destructor logging macros are redundant 1.84 +// for refcounted objects that log via the NS_LOG_ADDREF/NS_LOG_RELEASE macros. 1.85 +// Refcount logging is preferred. 1.86 +#define MOZ_COUNT_CTOR(_type) \ 1.87 +do { \ 1.88 + NS_LogCtor((void*)this, #_type, sizeof(*this)); \ 1.89 +} while (0) 1.90 + 1.91 +#define MOZ_COUNT_CTOR_INHERITED(_type, _base) \ 1.92 +do { \ 1.93 + NS_LogCtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \ 1.94 +} while (0) 1.95 + 1.96 +#define MOZ_COUNT_DTOR(_type) \ 1.97 +do { \ 1.98 + NS_LogDtor((void*)this, #_type, sizeof(*this)); \ 1.99 +} while (0) 1.100 + 1.101 +#define MOZ_COUNT_DTOR_INHERITED(_type, _base) \ 1.102 +do { \ 1.103 + NS_LogDtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \ 1.104 +} while (0) 1.105 + 1.106 +/* nsCOMPtr.h allows these macros to be defined by clients 1.107 + * These logging functions require dynamic_cast<void*>, so they don't 1.108 + * do anything useful if we don't have dynamic_cast<void*>. */ 1.109 +#define NSCAP_LOG_ASSIGNMENT(_c, _p) \ 1.110 + if (_p) \ 1.111 + NS_LogCOMPtrAddRef((_c),static_cast<nsISupports*>(_p)) 1.112 + 1.113 +#define NSCAP_LOG_RELEASE(_c, _p) \ 1.114 + if (_p) \ 1.115 + NS_LogCOMPtrRelease((_c), static_cast<nsISupports*>(_p)) 1.116 + 1.117 +#else /* !NS_BUILD_REFCNT_LOGGING */ 1.118 + 1.119 +#define NS_LOG_ADDREF(_p, _rc, _type, _size) 1.120 +#define NS_LOG_RELEASE(_p, _rc, _type) 1.121 +#define MOZ_COUNT_CTOR(_type) 1.122 +#define MOZ_COUNT_CTOR_INHERITED(_type, _base) 1.123 +#define MOZ_COUNT_DTOR(_type) 1.124 +#define MOZ_COUNT_DTOR_INHERITED(_type, _base) 1.125 + 1.126 +#endif /* NS_BUILD_REFCNT_LOGGING */ 1.127 + 1.128 + 1.129 +// Support for ISupports classes which interact with cycle collector. 1.130 + 1.131 +#define NS_NUMBER_OF_FLAGS_IN_REFCNT 2 1.132 +#define NS_IN_PURPLE_BUFFER (1 << 0) 1.133 +#define NS_IS_PURPLE (1 << 1) 1.134 +#define NS_REFCOUNT_CHANGE (1 << NS_NUMBER_OF_FLAGS_IN_REFCNT) 1.135 +#define NS_REFCOUNT_VALUE(_val) (_val >> NS_NUMBER_OF_FLAGS_IN_REFCNT) 1.136 + 1.137 +class nsCycleCollectingAutoRefCnt { 1.138 + 1.139 +public: 1.140 + nsCycleCollectingAutoRefCnt() 1.141 + : mRefCntAndFlags(0) 1.142 + {} 1.143 + 1.144 + nsCycleCollectingAutoRefCnt(uintptr_t aValue) 1.145 + : mRefCntAndFlags(aValue << NS_NUMBER_OF_FLAGS_IN_REFCNT) 1.146 + { 1.147 + } 1.148 + 1.149 + MOZ_ALWAYS_INLINE uintptr_t incr(nsISupports *owner) 1.150 + { 1.151 + return incr(owner, nullptr); 1.152 + } 1.153 + 1.154 + MOZ_ALWAYS_INLINE uintptr_t incr(void *owner, nsCycleCollectionParticipant *p) 1.155 + { 1.156 + mRefCntAndFlags += NS_REFCOUNT_CHANGE; 1.157 + mRefCntAndFlags &= ~NS_IS_PURPLE; 1.158 + // For incremental cycle collection, use the purple buffer to track objects 1.159 + // that have been AddRef'd. 1.160 + if (!IsInPurpleBuffer()) { 1.161 + mRefCntAndFlags |= NS_IN_PURPLE_BUFFER; 1.162 + // Refcount isn't zero, so Suspect won't delete anything. 1.163 + MOZ_ASSERT(get() > 0); 1.164 + NS_CycleCollectorSuspect3(owner, p, this, nullptr); 1.165 + } 1.166 + return NS_REFCOUNT_VALUE(mRefCntAndFlags); 1.167 + } 1.168 + 1.169 + MOZ_ALWAYS_INLINE void stabilizeForDeletion() 1.170 + { 1.171 + // Set refcnt to 1 and mark us to be in the purple buffer. 1.172 + // This way decr won't call suspect again. 1.173 + mRefCntAndFlags = NS_REFCOUNT_CHANGE | NS_IN_PURPLE_BUFFER; 1.174 + } 1.175 + 1.176 + MOZ_ALWAYS_INLINE uintptr_t decr(nsISupports *owner, 1.177 + bool *shouldDelete = nullptr) 1.178 + { 1.179 + return decr(owner, nullptr, shouldDelete); 1.180 + } 1.181 + 1.182 + MOZ_ALWAYS_INLINE uintptr_t decr(void *owner, nsCycleCollectionParticipant *p, 1.183 + bool *shouldDelete = nullptr) 1.184 + { 1.185 + MOZ_ASSERT(get() > 0); 1.186 + if (!IsInPurpleBuffer()) { 1.187 + mRefCntAndFlags -= NS_REFCOUNT_CHANGE; 1.188 + mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE); 1.189 + uintptr_t retval = NS_REFCOUNT_VALUE(mRefCntAndFlags); 1.190 + // Suspect may delete 'owner' and 'this'! 1.191 + NS_CycleCollectorSuspect3(owner, p, this, shouldDelete); 1.192 + return retval; 1.193 + } 1.194 + mRefCntAndFlags -= NS_REFCOUNT_CHANGE; 1.195 + mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE); 1.196 + return NS_REFCOUNT_VALUE(mRefCntAndFlags); 1.197 + } 1.198 + 1.199 + MOZ_ALWAYS_INLINE void RemovePurple() 1.200 + { 1.201 + MOZ_ASSERT(IsPurple(), "must be purple"); 1.202 + mRefCntAndFlags &= ~NS_IS_PURPLE; 1.203 + } 1.204 + 1.205 + MOZ_ALWAYS_INLINE void RemoveFromPurpleBuffer() 1.206 + { 1.207 + MOZ_ASSERT(IsInPurpleBuffer()); 1.208 + mRefCntAndFlags &= ~(NS_IS_PURPLE | NS_IN_PURPLE_BUFFER); 1.209 + } 1.210 + 1.211 + MOZ_ALWAYS_INLINE bool IsPurple() const 1.212 + { 1.213 + return !!(mRefCntAndFlags & NS_IS_PURPLE); 1.214 + } 1.215 + 1.216 + MOZ_ALWAYS_INLINE bool IsInPurpleBuffer() const 1.217 + { 1.218 + return !!(mRefCntAndFlags & NS_IN_PURPLE_BUFFER); 1.219 + } 1.220 + 1.221 + MOZ_ALWAYS_INLINE nsrefcnt get() const 1.222 + { 1.223 + return NS_REFCOUNT_VALUE(mRefCntAndFlags); 1.224 + } 1.225 + 1.226 + MOZ_ALWAYS_INLINE operator nsrefcnt() const 1.227 + { 1.228 + return get(); 1.229 + } 1.230 + 1.231 + private: 1.232 + uintptr_t mRefCntAndFlags; 1.233 +}; 1.234 + 1.235 +class nsAutoRefCnt { 1.236 + 1.237 + public: 1.238 + nsAutoRefCnt() : mValue(0) {} 1.239 + nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {} 1.240 + 1.241 + // only support prefix increment/decrement 1.242 + nsrefcnt operator++() { return ++mValue; } 1.243 + nsrefcnt operator--() { return --mValue; } 1.244 + 1.245 + nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); } 1.246 + operator nsrefcnt() const { return mValue; } 1.247 + nsrefcnt get() const { return mValue; } 1.248 + 1.249 + static const bool isThreadSafe = false; 1.250 + private: 1.251 + nsrefcnt operator++(int) MOZ_DELETE; 1.252 + nsrefcnt operator--(int) MOZ_DELETE; 1.253 + nsrefcnt mValue; 1.254 +}; 1.255 + 1.256 +#ifndef XPCOM_GLUE 1.257 +namespace mozilla { 1.258 +class ThreadSafeAutoRefCnt { 1.259 + public: 1.260 + ThreadSafeAutoRefCnt() : mValue(0) {} 1.261 + ThreadSafeAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {} 1.262 + 1.263 + // only support prefix increment/decrement 1.264 + MOZ_ALWAYS_INLINE nsrefcnt operator++() { return ++mValue; } 1.265 + MOZ_ALWAYS_INLINE nsrefcnt operator--() { return --mValue; } 1.266 + 1.267 + MOZ_ALWAYS_INLINE nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); } 1.268 + MOZ_ALWAYS_INLINE operator nsrefcnt() const { return mValue; } 1.269 + MOZ_ALWAYS_INLINE nsrefcnt get() const { return mValue; } 1.270 + 1.271 + static const bool isThreadSafe = true; 1.272 + private: 1.273 + nsrefcnt operator++(int) MOZ_DELETE; 1.274 + nsrefcnt operator--(int) MOZ_DELETE; 1.275 + // In theory, RelaseAcquire consistency (but no weaker) is sufficient for 1.276 + // the counter. Making it weaker could speed up builds on ARM (but not x86), 1.277 + // but could break pre-existing code that assumes sequential consistency. 1.278 + Atomic<nsrefcnt> mValue; 1.279 +}; 1.280 +} 1.281 +#endif 1.282 + 1.283 +/////////////////////////////////////////////////////////////////////////////// 1.284 + 1.285 +/** 1.286 + * Declare the reference count variable and the implementations of the 1.287 + * AddRef and QueryInterface methods. 1.288 + */ 1.289 + 1.290 +#define NS_DECL_ISUPPORTS \ 1.291 +public: \ 1.292 + NS_IMETHOD QueryInterface(REFNSIID aIID, \ 1.293 + void** aInstancePtr); \ 1.294 + NS_IMETHOD_(MozExternalRefCountType) AddRef(void); \ 1.295 + NS_IMETHOD_(MozExternalRefCountType) Release(void); \ 1.296 +protected: \ 1.297 + nsAutoRefCnt mRefCnt; \ 1.298 + NS_DECL_OWNINGTHREAD \ 1.299 +public: 1.300 + 1.301 +#define NS_DECL_THREADSAFE_ISUPPORTS \ 1.302 +public: \ 1.303 + NS_IMETHOD QueryInterface(REFNSIID aIID, \ 1.304 + void** aInstancePtr); \ 1.305 + NS_IMETHOD_(MozExternalRefCountType) AddRef(void); \ 1.306 + NS_IMETHOD_(MozExternalRefCountType) Release(void); \ 1.307 +protected: \ 1.308 + ::mozilla::ThreadSafeAutoRefCnt mRefCnt; \ 1.309 + NS_DECL_OWNINGTHREAD \ 1.310 +public: 1.311 + 1.312 +#define NS_DECL_CYCLE_COLLECTING_ISUPPORTS \ 1.313 +public: \ 1.314 + NS_IMETHOD QueryInterface(REFNSIID aIID, \ 1.315 + void** aInstancePtr); \ 1.316 + NS_IMETHOD_(MozExternalRefCountType) AddRef(void); \ 1.317 + NS_IMETHOD_(MozExternalRefCountType) Release(void); \ 1.318 + NS_IMETHOD_(void) DeleteCycleCollectable(void); \ 1.319 +protected: \ 1.320 + nsCycleCollectingAutoRefCnt mRefCnt; \ 1.321 + NS_DECL_OWNINGTHREAD \ 1.322 +public: 1.323 + 1.324 + 1.325 +/////////////////////////////////////////////////////////////////////////////// 1.326 + 1.327 +/* 1.328 + * Implementation of AddRef and Release for non-nsISupports (ie "native") 1.329 + * cycle-collected classes that use the purple buffer to avoid leaks. 1.330 + */ 1.331 + 1.332 +#define NS_IMPL_CC_NATIVE_ADDREF_BODY(_class) \ 1.333 + MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ 1.334 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.335 + nsrefcnt count = \ 1.336 + mRefCnt.incr(static_cast<void*>(this), \ 1.337 + _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \ 1.338 + NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \ 1.339 + return count; 1.340 + 1.341 +#define NS_IMPL_CC_NATIVE_RELEASE_BODY(_class) \ 1.342 + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ 1.343 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.344 + nsrefcnt count = \ 1.345 + mRefCnt.decr(static_cast<void*>(this), \ 1.346 + _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \ 1.347 + NS_LOG_RELEASE(this, count, #_class); \ 1.348 + return count; 1.349 + 1.350 +#define NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(_class) \ 1.351 +NS_METHOD_(MozExternalRefCountType) _class::AddRef(void) \ 1.352 +{ \ 1.353 + NS_IMPL_CC_NATIVE_ADDREF_BODY(_class) \ 1.354 +} 1.355 + 1.356 +#define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE(_class, _last) \ 1.357 +NS_METHOD_(MozExternalRefCountType) _class::Release(void) \ 1.358 +{ \ 1.359 + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ 1.360 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.361 + bool shouldDelete = false; \ 1.362 + nsrefcnt count = \ 1.363 + mRefCnt.decr(static_cast<void*>(this), \ 1.364 + _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant(), \ 1.365 + &shouldDelete); \ 1.366 + NS_LOG_RELEASE(this, count, #_class); \ 1.367 + if (count == 0) { \ 1.368 + mRefCnt.incr(static_cast<void*>(this), \ 1.369 + _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \ 1.370 + _last; \ 1.371 + mRefCnt.decr(static_cast<void*>(this), \ 1.372 + _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \ 1.373 + if (shouldDelete) { \ 1.374 + mRefCnt.stabilizeForDeletion(); \ 1.375 + DeleteCycleCollectable(); \ 1.376 + } \ 1.377 + } \ 1.378 + return count; \ 1.379 +} 1.380 + 1.381 +#define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(_class) \ 1.382 +NS_METHOD_(MozExternalRefCountType) _class::Release(void) \ 1.383 +{ \ 1.384 + NS_IMPL_CC_NATIVE_RELEASE_BODY(_class) \ 1.385 +} 1.386 + 1.387 +#define NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(_class) \ 1.388 +public: \ 1.389 + NS_METHOD_(MozExternalRefCountType) AddRef(void) { \ 1.390 + NS_IMPL_CC_NATIVE_ADDREF_BODY(_class) \ 1.391 + } \ 1.392 + NS_METHOD_(MozExternalRefCountType) Release(void) { \ 1.393 + NS_IMPL_CC_NATIVE_RELEASE_BODY(_class) \ 1.394 + } \ 1.395 +protected: \ 1.396 + nsCycleCollectingAutoRefCnt mRefCnt; \ 1.397 + NS_DECL_OWNINGTHREAD \ 1.398 +public: 1.399 + 1.400 + 1.401 +/////////////////////////////////////////////////////////////////////////////// 1.402 + 1.403 +/** 1.404 + * Previously used to initialize the reference count, but no longer needed. 1.405 + * 1.406 + * DEPRECATED. 1.407 + */ 1.408 +#define NS_INIT_ISUPPORTS() ((void)0) 1.409 + 1.410 +/** 1.411 + * Use this macro to declare and implement the AddRef & Release methods for a 1.412 + * given non-XPCOM <i>_class</i>. 1.413 + * 1.414 + * @param _class The name of the class implementing the method 1.415 + */ 1.416 +#define NS_INLINE_DECL_REFCOUNTING(_class) \ 1.417 +public: \ 1.418 + NS_METHOD_(MozExternalRefCountType) AddRef(void) { \ 1.419 + MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ 1.420 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.421 + ++mRefCnt; \ 1.422 + NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \ 1.423 + return mRefCnt; \ 1.424 + } \ 1.425 + NS_METHOD_(MozExternalRefCountType) Release(void) { \ 1.426 + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ 1.427 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.428 + --mRefCnt; \ 1.429 + NS_LOG_RELEASE(this, mRefCnt, #_class); \ 1.430 + if (mRefCnt == 0) { \ 1.431 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.432 + mRefCnt = 1; /* stabilize */ \ 1.433 + delete this; \ 1.434 + return 0; \ 1.435 + } \ 1.436 + return mRefCnt; \ 1.437 + } \ 1.438 +protected: \ 1.439 + nsAutoRefCnt mRefCnt; \ 1.440 + NS_DECL_OWNINGTHREAD \ 1.441 +public: 1.442 + 1.443 +/** 1.444 + * Use this macro to declare and implement the AddRef & Release methods for a 1.445 + * given non-XPCOM <i>_class</i> in a threadsafe manner. 1.446 + * 1.447 + * DOES NOT DO REFCOUNT STABILIZATION! 1.448 + * 1.449 + * @param _class The name of the class implementing the method 1.450 + */ 1.451 +#define NS_INLINE_DECL_THREADSAFE_REFCOUNTING(_class) \ 1.452 +public: \ 1.453 + NS_METHOD_(MozExternalRefCountType) AddRef(void) { \ 1.454 + MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ 1.455 + nsrefcnt count = ++mRefCnt; \ 1.456 + NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \ 1.457 + return (nsrefcnt) count; \ 1.458 + } \ 1.459 + NS_METHOD_(MozExternalRefCountType) Release(void) { \ 1.460 + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ 1.461 + nsrefcnt count = --mRefCnt; \ 1.462 + NS_LOG_RELEASE(this, count, #_class); \ 1.463 + if (count == 0) { \ 1.464 + delete (this); \ 1.465 + return 0; \ 1.466 + } \ 1.467 + return count; \ 1.468 + } \ 1.469 +protected: \ 1.470 + ::mozilla::ThreadSafeAutoRefCnt mRefCnt; \ 1.471 +public: 1.472 + 1.473 +/** 1.474 + * Use this macro to implement the AddRef method for a given <i>_class</i> 1.475 + * @param _class The name of the class implementing the method 1.476 + */ 1.477 +#define NS_IMPL_ADDREF(_class) \ 1.478 +NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void) \ 1.479 +{ \ 1.480 + MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ 1.481 + if (!mRefCnt.isThreadSafe) \ 1.482 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.483 + nsrefcnt count = ++mRefCnt; \ 1.484 + NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \ 1.485 + return count; \ 1.486 +} 1.487 + 1.488 +/** 1.489 + * Use this macro to implement the AddRef method for a given <i>_class</i> 1.490 + * implemented as a wholly owned aggregated object intended to implement 1.491 + * interface(s) for its owner 1.492 + * @param _class The name of the class implementing the method 1.493 + * @param _aggregator the owning/containing object 1.494 + */ 1.495 +#define NS_IMPL_ADDREF_USING_AGGREGATOR(_class, _aggregator) \ 1.496 +NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void) \ 1.497 +{ \ 1.498 + NS_PRECONDITION(_aggregator, "null aggregator"); \ 1.499 + return (_aggregator)->AddRef(); \ 1.500 +} 1.501 + 1.502 +/** 1.503 + * Use this macro to implement the Release method for a given 1.504 + * <i>_class</i>. 1.505 + * @param _class The name of the class implementing the method 1.506 + * @param _destroy A statement that is executed when the object's 1.507 + * refcount drops to zero. 1.508 + * 1.509 + * For example, 1.510 + * 1.511 + * NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this)) 1.512 + * 1.513 + * will cause 1.514 + * 1.515 + * Destroy(this); 1.516 + * 1.517 + * to be invoked when the object's refcount drops to zero. This 1.518 + * allows for arbitrary teardown activity to occur (e.g., deallocation 1.519 + * of object allocated with placement new). 1.520 + */ 1.521 +#define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy) \ 1.522 +NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \ 1.523 +{ \ 1.524 + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ 1.525 + if (!mRefCnt.isThreadSafe) \ 1.526 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.527 + nsrefcnt count = --mRefCnt; \ 1.528 + NS_LOG_RELEASE(this, count, #_class); \ 1.529 + if (count == 0) { \ 1.530 + if (!mRefCnt.isThreadSafe) \ 1.531 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.532 + mRefCnt = 1; /* stabilize */ \ 1.533 + _destroy; \ 1.534 + return 0; \ 1.535 + } \ 1.536 + return count; \ 1.537 +} 1.538 + 1.539 +/** 1.540 + * Use this macro to implement the Release method for a given <i>_class</i> 1.541 + * @param _class The name of the class implementing the method 1.542 + * 1.543 + * A note on the 'stabilization' of the refcnt to one. At that point, 1.544 + * the object's refcount will have gone to zero. The object's 1.545 + * destructor may trigger code that attempts to QueryInterface() and 1.546 + * Release() 'this' again. Doing so will temporarily increment and 1.547 + * decrement the refcount. (Only a logic error would make one try to 1.548 + * keep a permanent hold on 'this'.) To prevent re-entering the 1.549 + * destructor, we make sure that no balanced refcounting can return 1.550 + * the refcount to |0|. 1.551 + */ 1.552 +#define NS_IMPL_RELEASE(_class) \ 1.553 + NS_IMPL_RELEASE_WITH_DESTROY(_class, delete (this)) 1.554 + 1.555 +/** 1.556 + * Use this macro to implement the Release method for a given <i>_class</i> 1.557 + * implemented as a wholly owned aggregated object intended to implement 1.558 + * interface(s) for its owner 1.559 + * @param _class The name of the class implementing the method 1.560 + * @param _aggregator the owning/containing object 1.561 + */ 1.562 +#define NS_IMPL_RELEASE_USING_AGGREGATOR(_class, _aggregator) \ 1.563 +NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \ 1.564 +{ \ 1.565 + NS_PRECONDITION(_aggregator, "null aggregator"); \ 1.566 + return (_aggregator)->Release(); \ 1.567 +} 1.568 + 1.569 + 1.570 +#define NS_IMPL_CYCLE_COLLECTING_ADDREF(_class) \ 1.571 +NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void) \ 1.572 +{ \ 1.573 + MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \ 1.574 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.575 + nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \ 1.576 + nsrefcnt count = mRefCnt.incr(base); \ 1.577 + NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \ 1.578 + return count; \ 1.579 +} 1.580 + 1.581 +#define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, _destroy) \ 1.582 +NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \ 1.583 +{ \ 1.584 + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ 1.585 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.586 + nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \ 1.587 + nsrefcnt count = mRefCnt.decr(base); \ 1.588 + NS_LOG_RELEASE(this, count, #_class); \ 1.589 + return count; \ 1.590 +} \ 1.591 +NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void) \ 1.592 +{ \ 1.593 + _destroy; \ 1.594 +} 1.595 + 1.596 +#define NS_IMPL_CYCLE_COLLECTING_RELEASE(_class) \ 1.597 + NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, delete (this)) 1.598 + 1.599 +// _LAST_RELEASE can be useful when certain resources should be released 1.600 +// as soon as we know the object will be deleted. 1.601 +#define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(_class, _last) \ 1.602 +NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \ 1.603 +{ \ 1.604 + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \ 1.605 + NS_ASSERT_OWNINGTHREAD(_class); \ 1.606 + bool shouldDelete = false; \ 1.607 + nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \ 1.608 + nsrefcnt count = mRefCnt.decr(base, &shouldDelete); \ 1.609 + NS_LOG_RELEASE(this, count, #_class); \ 1.610 + if (count == 0) { \ 1.611 + mRefCnt.incr(base); \ 1.612 + _last; \ 1.613 + mRefCnt.decr(base); \ 1.614 + if (shouldDelete) { \ 1.615 + mRefCnt.stabilizeForDeletion(); \ 1.616 + DeleteCycleCollectable(); \ 1.617 + } \ 1.618 + } \ 1.619 + return count; \ 1.620 +} \ 1.621 +NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void) \ 1.622 +{ \ 1.623 + delete this; \ 1.624 +} 1.625 + 1.626 +/////////////////////////////////////////////////////////////////////////////// 1.627 + 1.628 +/** 1.629 + * There are two ways of implementing QueryInterface, and we use both: 1.630 + * 1.631 + * Table-driven QueryInterface uses a static table of IID->offset mappings 1.632 + * and a shared helper function. Using it tends to reduce codesize and improve 1.633 + * runtime performance (due to processor cache hits). 1.634 + * 1.635 + * Macro-driven QueryInterface generates a QueryInterface function directly 1.636 + * using common macros. This is necessary if special QueryInterface features 1.637 + * are being used (such as tearoffs and conditional interfaces). 1.638 + * 1.639 + * These methods can be combined into a table-driven function call followed 1.640 + * by custom code for tearoffs and conditionals. 1.641 + */ 1.642 + 1.643 +struct QITableEntry 1.644 +{ 1.645 + const nsIID *iid; // null indicates end of the QITableEntry array 1.646 + int32_t offset; 1.647 +}; 1.648 + 1.649 +NS_COM_GLUE nsresult NS_FASTCALL 1.650 +NS_TableDrivenQI(void* aThis, REFNSIID aIID, 1.651 + void **aInstancePtr, const QITableEntry* entries); 1.652 + 1.653 +/** 1.654 + * Implement table-driven queryinterface 1.655 + */ 1.656 + 1.657 +#define NS_INTERFACE_TABLE_HEAD(_class) \ 1.658 +NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \ 1.659 +{ \ 1.660 + NS_ASSERTION(aInstancePtr, \ 1.661 + "QueryInterface requires a non-NULL destination!"); \ 1.662 + nsresult rv = NS_ERROR_FAILURE; 1.663 + 1.664 +#define NS_INTERFACE_TABLE_BEGIN \ 1.665 + static const QITableEntry table[] = { 1.666 + 1.667 +#define NS_INTERFACE_TABLE_ENTRY(_class, _interface) \ 1.668 + { &_interface::COMTypeInfo<int>::kIID, \ 1.669 + int32_t(reinterpret_cast<char*>( \ 1.670 + static_cast<_interface*>((_class*) 0x1000)) - \ 1.671 + reinterpret_cast<char*>((_class*) 0x1000)) \ 1.672 + }, 1.673 + 1.674 +#define NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, _interface, _implClass) \ 1.675 + { &_interface::COMTypeInfo<int>::kIID, \ 1.676 + int32_t(reinterpret_cast<char*>( \ 1.677 + static_cast<_interface*>( \ 1.678 + static_cast<_implClass*>( \ 1.679 + (_class*) 0x1000))) - \ 1.680 + reinterpret_cast<char*>((_class*) 0x1000)) \ 1.681 + }, 1.682 + 1.683 +/* 1.684 + * XXX: we want to use mozilla::ArrayLength (or equivalent, 1.685 + * MOZ_ARRAY_LENGTH) in this condition, but some versions of GCC don't 1.686 + * see that the static_assert condition is actually constant in those 1.687 + * cases, even with constexpr support (?). 1.688 + */ 1.689 +#define NS_INTERFACE_TABLE_END_WITH_PTR(_ptr) \ 1.690 + { nullptr, 0 } }; \ 1.691 + static_assert((sizeof(table)/sizeof(table[0])) > 1, "need at least 1 interface"); \ 1.692 + rv = NS_TableDrivenQI(static_cast<void*>(_ptr), \ 1.693 + aIID, aInstancePtr, table); 1.694 + 1.695 +#define NS_INTERFACE_TABLE_END \ 1.696 + NS_INTERFACE_TABLE_END_WITH_PTR(this) 1.697 + 1.698 +#define NS_INTERFACE_TABLE_TAIL \ 1.699 + return rv; \ 1.700 +} 1.701 + 1.702 +#define NS_INTERFACE_TABLE_TAIL_INHERITING(_baseclass) \ 1.703 + if (NS_SUCCEEDED(rv)) \ 1.704 + return rv; \ 1.705 + return _baseclass::QueryInterface(aIID, aInstancePtr); \ 1.706 +} 1.707 + 1.708 +#define NS_INTERFACE_TABLE_TAIL_USING_AGGREGATOR(_aggregator) \ 1.709 + if (NS_SUCCEEDED(rv)) \ 1.710 + return rv; \ 1.711 + NS_ASSERTION(_aggregator, "null aggregator"); \ 1.712 + return _aggregator->QueryInterface(aIID, aInstancePtr) \ 1.713 +} 1.714 + 1.715 +/** 1.716 + * This implements query interface with two assumptions: First, the 1.717 + * class in question implements nsISupports and its own interface and 1.718 + * nothing else. Second, the implementation of the class's primary 1.719 + * inheritance chain leads to its own interface. 1.720 + * 1.721 + * @param _class The name of the class implementing the method 1.722 + * @param _classiiddef The name of the #define symbol that defines the IID 1.723 + * for the class (e.g. NS_ISUPPORTS_IID) 1.724 + */ 1.725 + 1.726 +#define NS_IMPL_QUERY_HEAD(_class) \ 1.727 +NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \ 1.728 +{ \ 1.729 + NS_ASSERTION(aInstancePtr, \ 1.730 + "QueryInterface requires a non-NULL destination!"); \ 1.731 + nsISupports* foundInterface; 1.732 + 1.733 +#define NS_IMPL_QUERY_BODY(_interface) \ 1.734 + if ( aIID.Equals(NS_GET_IID(_interface)) ) \ 1.735 + foundInterface = static_cast<_interface*>(this); \ 1.736 + else 1.737 + 1.738 +#define NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition) \ 1.739 + if ( (condition) && aIID.Equals(NS_GET_IID(_interface))) \ 1.740 + foundInterface = static_cast<_interface*>(this); \ 1.741 + else 1.742 + 1.743 +#define NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass) \ 1.744 + if ( aIID.Equals(NS_GET_IID(_interface)) ) \ 1.745 + foundInterface = static_cast<_interface*>( \ 1.746 + static_cast<_implClass*>(this)); \ 1.747 + else 1.748 + 1.749 +#define NS_IMPL_QUERY_BODY_AGGREGATED(_interface, _aggregate) \ 1.750 + if ( aIID.Equals(NS_GET_IID(_interface)) ) \ 1.751 + foundInterface = static_cast<_interface*>(_aggregate); \ 1.752 + else 1.753 + 1.754 +#define NS_IMPL_QUERY_TAIL_GUTS \ 1.755 + foundInterface = 0; \ 1.756 + nsresult status; \ 1.757 + if ( !foundInterface ) \ 1.758 + { \ 1.759 + /* nsISupports should be handled by this point. If not, fail. */ \ 1.760 + MOZ_ASSERT(!aIID.Equals(NS_GET_IID(nsISupports))); \ 1.761 + status = NS_NOINTERFACE; \ 1.762 + } \ 1.763 + else \ 1.764 + { \ 1.765 + NS_ADDREF(foundInterface); \ 1.766 + status = NS_OK; \ 1.767 + } \ 1.768 + *aInstancePtr = foundInterface; \ 1.769 + return status; \ 1.770 +} 1.771 + 1.772 +#define NS_IMPL_QUERY_TAIL_INHERITING(_baseclass) \ 1.773 + foundInterface = 0; \ 1.774 + nsresult status; \ 1.775 + if ( !foundInterface ) \ 1.776 + status = _baseclass::QueryInterface(aIID, (void**)&foundInterface); \ 1.777 + else \ 1.778 + { \ 1.779 + NS_ADDREF(foundInterface); \ 1.780 + status = NS_OK; \ 1.781 + } \ 1.782 + *aInstancePtr = foundInterface; \ 1.783 + return status; \ 1.784 +} 1.785 + 1.786 +#define NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator) \ 1.787 + foundInterface = 0; \ 1.788 + nsresult status; \ 1.789 + if ( !foundInterface ) { \ 1.790 + NS_ASSERTION(_aggregator, "null aggregator"); \ 1.791 + status = _aggregator->QueryInterface(aIID, (void**)&foundInterface); \ 1.792 + } else \ 1.793 + { \ 1.794 + NS_ADDREF(foundInterface); \ 1.795 + status = NS_OK; \ 1.796 + } \ 1.797 + *aInstancePtr = foundInterface; \ 1.798 + return status; \ 1.799 +} 1.800 + 1.801 +#define NS_IMPL_QUERY_TAIL(_supports_interface) \ 1.802 + NS_IMPL_QUERY_BODY_AMBIGUOUS(nsISupports, _supports_interface) \ 1.803 + NS_IMPL_QUERY_TAIL_GUTS 1.804 + 1.805 + 1.806 + /* 1.807 + This is the new scheme. Using this notation now will allow us to switch to 1.808 + a table driven mechanism when it's ready. Note the difference between this 1.809 + and the (currently) underlying NS_IMPL_QUERY_INTERFACE mechanism. You must 1.810 + explicitly mention |nsISupports| when using the interface maps. 1.811 + */ 1.812 +#define NS_INTERFACE_MAP_BEGIN(_implClass) NS_IMPL_QUERY_HEAD(_implClass) 1.813 +#define NS_INTERFACE_MAP_ENTRY(_interface) NS_IMPL_QUERY_BODY(_interface) 1.814 +#define NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, condition) \ 1.815 + NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition) 1.816 +#define NS_INTERFACE_MAP_ENTRY_AGGREGATED(_interface,_aggregate) \ 1.817 + NS_IMPL_QUERY_BODY_AGGREGATED(_interface,_aggregate) 1.818 + 1.819 +#define NS_INTERFACE_MAP_END NS_IMPL_QUERY_TAIL_GUTS 1.820 +#define NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(_interface, _implClass) \ 1.821 + NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass) 1.822 +#define NS_INTERFACE_MAP_END_INHERITING(_baseClass) \ 1.823 + NS_IMPL_QUERY_TAIL_INHERITING(_baseClass) 1.824 +#define NS_INTERFACE_MAP_END_AGGREGATED(_aggregator) \ 1.825 + NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator) 1.826 + 1.827 +#define NS_INTERFACE_TABLE0(_class) \ 1.828 + NS_INTERFACE_TABLE_BEGIN \ 1.829 + NS_INTERFACE_TABLE_ENTRY(_class, nsISupports) \ 1.830 + NS_INTERFACE_TABLE_END 1.831 + 1.832 +#define NS_INTERFACE_TABLE(aClass, ...) \ 1.833 + MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \ 1.834 + NS_INTERFACE_TABLE_BEGIN \ 1.835 + MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \ 1.836 + NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(aClass, nsISupports, \ 1.837 + MOZ_ARG_1(__VA_ARGS__)) \ 1.838 + NS_INTERFACE_TABLE_END 1.839 + 1.840 +#define NS_IMPL_QUERY_INTERFACE0(_class) \ 1.841 + NS_INTERFACE_TABLE_HEAD(_class) \ 1.842 + NS_INTERFACE_TABLE0(_class) \ 1.843 + NS_INTERFACE_TABLE_TAIL 1.844 + 1.845 +#define NS_IMPL_QUERY_INTERFACE(aClass, ...) \ 1.846 + NS_INTERFACE_TABLE_HEAD(aClass) \ 1.847 + NS_INTERFACE_TABLE(aClass, __VA_ARGS__) \ 1.848 + NS_INTERFACE_TABLE_TAIL 1.849 + 1.850 +/** 1.851 + * Declare that you're going to inherit from something that already 1.852 + * implements nsISupports, but also implements an additional interface, thus 1.853 + * causing an ambiguity. In this case you don't need another mRefCnt, you 1.854 + * just need to forward the definitions to the appropriate superclass. E.g. 1.855 + * 1.856 + * class Bar : public Foo, public nsIBar { // both provide nsISupports 1.857 + * public: 1.858 + * NS_DECL_ISUPPORTS_INHERITED 1.859 + * ...other nsIBar and Bar methods... 1.860 + * }; 1.861 + */ 1.862 +#define NS_DECL_ISUPPORTS_INHERITED \ 1.863 +public: \ 1.864 + NS_IMETHOD QueryInterface(REFNSIID aIID, \ 1.865 + void** aInstancePtr); \ 1.866 + NS_IMETHOD_(MozExternalRefCountType) AddRef(void); \ 1.867 + NS_IMETHOD_(MozExternalRefCountType) Release(void); \ 1.868 + 1.869 +/** 1.870 + * These macros can be used in conjunction with NS_DECL_ISUPPORTS_INHERITED 1.871 + * to implement the nsISupports methods, forwarding the invocations to a 1.872 + * superclass that already implements nsISupports. 1.873 + * 1.874 + * Note that I didn't make these inlined because they're virtual methods. 1.875 + */ 1.876 + 1.877 +#define NS_IMPL_ADDREF_INHERITED(Class, Super) \ 1.878 +NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void) \ 1.879 +{ \ 1.880 + nsrefcnt r = Super::AddRef(); \ 1.881 + NS_LOG_ADDREF(this, r, #Class, sizeof(*this)); \ 1.882 + return r; \ 1.883 +} 1.884 + 1.885 +#define NS_IMPL_RELEASE_INHERITED(Class, Super) \ 1.886 +NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \ 1.887 +{ \ 1.888 + nsrefcnt r = Super::Release(); \ 1.889 + NS_LOG_RELEASE(this, r, #Class); \ 1.890 + return r; \ 1.891 +} 1.892 + 1.893 +/** 1.894 + * As above but not logging the addref/release; needed if the base 1.895 + * class might be aggregated. 1.896 + */ 1.897 +#define NS_IMPL_NONLOGGING_ADDREF_INHERITED(Class, Super) \ 1.898 +NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void) \ 1.899 +{ \ 1.900 + return Super::AddRef(); \ 1.901 +} 1.902 + 1.903 +#define NS_IMPL_NONLOGGING_RELEASE_INHERITED(Class, Super) \ 1.904 +NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \ 1.905 +{ \ 1.906 + return Super::Release(); \ 1.907 +} 1.908 + 1.909 +#define NS_INTERFACE_TABLE_INHERITED0(Class) /* Nothing to do here */ 1.910 + 1.911 +#define NS_INTERFACE_TABLE_INHERITED(aClass, ...) \ 1.912 + MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \ 1.913 + NS_INTERFACE_TABLE_BEGIN \ 1.914 + MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \ 1.915 + NS_INTERFACE_TABLE_END 1.916 + 1.917 +#define NS_IMPL_QUERY_INTERFACE_INHERITED0(aClass, aSuper) \ 1.918 + NS_INTERFACE_TABLE_HEAD(aClass) \ 1.919 + NS_INTERFACE_TABLE_INHERITED0(aClass) \ 1.920 + NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper) 1.921 + 1.922 +#define NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, ...) \ 1.923 + NS_INTERFACE_TABLE_HEAD(aClass) \ 1.924 + NS_INTERFACE_TABLE_INHERITED(aClass, __VA_ARGS__) \ 1.925 + NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper) 1.926 + 1.927 +/** 1.928 + * Convenience macros for implementing all nsISupports methods for 1.929 + * a simple class. 1.930 + * @param _class The name of the class implementing the method 1.931 + * @param _classiiddef The name of the #define symbol that defines the IID 1.932 + * for the class (e.g. NS_ISUPPORTS_IID) 1.933 + */ 1.934 + 1.935 +#define NS_IMPL_ISUPPORTS0(_class) \ 1.936 + NS_IMPL_ADDREF(_class) \ 1.937 + NS_IMPL_RELEASE(_class) \ 1.938 + NS_IMPL_QUERY_INTERFACE0(_class) 1.939 + 1.940 +#define NS_IMPL_ISUPPORTS(aClass, ...) \ 1.941 + NS_IMPL_ADDREF(aClass) \ 1.942 + NS_IMPL_RELEASE(aClass) \ 1.943 + NS_IMPL_QUERY_INTERFACE(aClass, __VA_ARGS__) 1.944 + 1.945 +#define NS_IMPL_ISUPPORTS_INHERITED0(aClass, aSuper) \ 1.946 + NS_IMPL_QUERY_INTERFACE_INHERITED0(aClass, aSuper) \ 1.947 + NS_IMPL_ADDREF_INHERITED(aClass, aSuper) \ 1.948 + NS_IMPL_RELEASE_INHERITED(aClass, aSuper) \ 1.949 + 1.950 +#define NS_IMPL_ISUPPORTS_INHERITED(aClass, aSuper, ...) \ 1.951 + NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, __VA_ARGS__) \ 1.952 + NS_IMPL_ADDREF_INHERITED(aClass, aSuper) \ 1.953 + NS_IMPL_RELEASE_INHERITED(aClass, aSuper) 1.954 + 1.955 +/* 1.956 + * Macro to glue together a QI that starts with an interface table 1.957 + * and segues into an interface map (e.g. it uses singleton classinfo 1.958 + * or tearoffs). 1.959 + */ 1.960 +#define NS_INTERFACE_TABLE_TO_MAP_SEGUE \ 1.961 + if (rv == NS_OK) return rv; \ 1.962 + nsISupports* foundInterface; 1.963 + 1.964 + 1.965 +/////////////////////////////////////////////////////////////////////////////// 1.966 +/** 1.967 + * 1.968 + * Threadsafe implementations of the ISupports convenience macros. 1.969 + * 1.970 + * @note These are not available when linking against the standalone glue, 1.971 + * because the implementation requires PR_ symbols. 1.972 + */ 1.973 +#define NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_QUERY_TAIL_GUTS 1.974 + 1.975 +/** 1.976 + * Macro to generate nsIClassInfo methods for classes which do not have 1.977 + * corresponding nsIFactory implementations. 1.978 + */ 1.979 +#define NS_IMPL_THREADSAFE_CI(_class) \ 1.980 +NS_IMETHODIMP \ 1.981 +_class::GetInterfaces(uint32_t* _count, nsIID*** _array) \ 1.982 +{ \ 1.983 + return NS_CI_INTERFACE_GETTER_NAME(_class)(_count, _array); \ 1.984 +} \ 1.985 + \ 1.986 +NS_IMETHODIMP \ 1.987 +_class::GetHelperForLanguage(uint32_t _language, nsISupports** _retval) \ 1.988 +{ \ 1.989 + *_retval = nullptr; \ 1.990 + return NS_OK; \ 1.991 +} \ 1.992 + \ 1.993 +NS_IMETHODIMP \ 1.994 +_class::GetContractID(char** _contractID) \ 1.995 +{ \ 1.996 + *_contractID = nullptr; \ 1.997 + return NS_OK; \ 1.998 +} \ 1.999 + \ 1.1000 +NS_IMETHODIMP \ 1.1001 +_class::GetClassDescription(char** _classDescription) \ 1.1002 +{ \ 1.1003 + *_classDescription = nullptr; \ 1.1004 + return NS_OK; \ 1.1005 +} \ 1.1006 + \ 1.1007 +NS_IMETHODIMP \ 1.1008 +_class::GetClassID(nsCID** _classID) \ 1.1009 +{ \ 1.1010 + *_classID = nullptr; \ 1.1011 + return NS_OK; \ 1.1012 +} \ 1.1013 + \ 1.1014 +NS_IMETHODIMP \ 1.1015 +_class::GetImplementationLanguage(uint32_t* _language) \ 1.1016 +{ \ 1.1017 + *_language = nsIProgrammingLanguage::CPLUSPLUS; \ 1.1018 + return NS_OK; \ 1.1019 +} \ 1.1020 + \ 1.1021 +NS_IMETHODIMP \ 1.1022 +_class::GetFlags(uint32_t* _flags) \ 1.1023 +{ \ 1.1024 + *_flags = nsIClassInfo::THREADSAFE; \ 1.1025 + return NS_OK; \ 1.1026 +} \ 1.1027 + \ 1.1028 +NS_IMETHODIMP \ 1.1029 +_class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc) \ 1.1030 +{ \ 1.1031 + return NS_ERROR_NOT_AVAILABLE; \ 1.1032 +} 1.1033 + 1.1034 +#endif