nsISupportsImpl.h 53 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. /* -*- Mode: C++; tab-width: 8; 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. // IWYU pragma: private, include "nsISupports.h"
  6. #ifndef nsISupportsImpl_h__
  7. #define nsISupportsImpl_h__
  8. #include "nscore.h"
  9. #include "nsISupportsBase.h"
  10. #include "nsISupportsUtils.h"
  11. #if !defined(XPCOM_GLUE_AVOID_NSPR)
  12. #include "prthread.h" /* needed for thread-safety checks */
  13. #endif // !XPCOM_GLUE_AVOID_NSPR
  14. #include "nsDebug.h"
  15. #include "nsXPCOM.h"
  16. #include "mozilla/Atomics.h"
  17. #include "mozilla/Attributes.h"
  18. #include "mozilla/Assertions.h"
  19. #include "mozilla/Compiler.h"
  20. #include "mozilla/Likely.h"
  21. #include "mozilla/MacroArgs.h"
  22. #include "mozilla/MacroForEach.h"
  23. #include "mozilla/TypeTraits.h"
  24. #define MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(X) \
  25. static_assert(!mozilla::IsDestructible<X>::value, \
  26. "Reference-counted class " #X " should not have a public destructor. " \
  27. "Make this class's destructor non-public");
  28. inline nsISupports*
  29. ToSupports(nsISupports* aSupports)
  30. {
  31. return aSupports;
  32. }
  33. inline nsISupports*
  34. ToCanonicalSupports(nsISupports* aSupports)
  35. {
  36. return nullptr;
  37. }
  38. ////////////////////////////////////////////////////////////////////////////////
  39. // Macros to help detect thread-safety:
  40. #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
  41. class nsAutoOwningThread
  42. {
  43. public:
  44. nsAutoOwningThread() { mThread = PR_GetCurrentThread(); }
  45. void* GetThread() const { return mThread; }
  46. private:
  47. void* mThread;
  48. };
  49. #define NS_DECL_OWNINGTHREAD nsAutoOwningThread _mOwningThread;
  50. #define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) \
  51. NS_CheckThreadSafe(agg->_mOwningThread.GetThread(), #_class " not thread-safe")
  52. #define NS_ASSERT_OWNINGTHREAD(_class) NS_ASSERT_OWNINGTHREAD_AGGREGATE(this, _class)
  53. #else // !DEBUG && !(NIGHTLY_BUILD && !MOZ_PROFILING)
  54. #define NS_DECL_OWNINGTHREAD /* nothing */
  55. #define NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class) ((void)0)
  56. #define NS_ASSERT_OWNINGTHREAD(_class) ((void)0)
  57. #endif // DEBUG || (NIGHTLY_BUILD && !MOZ_PROFILING)
  58. // Macros for reference-count and constructor logging
  59. #if defined(NS_BUILD_REFCNT_LOGGING)
  60. #define NS_LOG_ADDREF(_p, _rc, _type, _size) \
  61. NS_LogAddRef((_p), (_rc), (_type), (uint32_t) (_size))
  62. #define NS_LOG_RELEASE(_p, _rc, _type) \
  63. NS_LogRelease((_p), (_rc), (_type))
  64. #include "mozilla/TypeTraits.h"
  65. #define MOZ_ASSERT_CLASSNAME(_type) \
  66. static_assert(mozilla::IsClass<_type>::value, \
  67. "Token '" #_type "' is not a class type.")
  68. // Note that the following constructor/destructor logging macros are redundant
  69. // for refcounted objects that log via the NS_LOG_ADDREF/NS_LOG_RELEASE macros.
  70. // Refcount logging is preferred.
  71. #define MOZ_COUNT_CTOR(_type) \
  72. do { \
  73. MOZ_ASSERT_CLASSNAME(_type); \
  74. NS_LogCtor((void*)this, #_type, sizeof(*this)); \
  75. } while (0)
  76. #define MOZ_COUNT_CTOR_INHERITED(_type, _base) \
  77. do { \
  78. MOZ_ASSERT_CLASSNAME(_type); \
  79. MOZ_ASSERT_CLASSNAME(_base); \
  80. NS_LogCtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
  81. } while (0)
  82. #define MOZ_LOG_CTOR(_ptr, _name, _size) \
  83. do { \
  84. NS_LogCtor((void*)_ptr, _name, _size); \
  85. } while (0)
  86. #define MOZ_COUNT_DTOR(_type) \
  87. do { \
  88. MOZ_ASSERT_CLASSNAME(_type); \
  89. NS_LogDtor((void*)this, #_type, sizeof(*this)); \
  90. } while (0)
  91. #define MOZ_COUNT_DTOR_INHERITED(_type, _base) \
  92. do { \
  93. MOZ_ASSERT_CLASSNAME(_type); \
  94. MOZ_ASSERT_CLASSNAME(_base); \
  95. NS_LogDtor((void*)this, #_type, sizeof(*this) - sizeof(_base)); \
  96. } while (0)
  97. #define MOZ_LOG_DTOR(_ptr, _name, _size) \
  98. do { \
  99. NS_LogDtor((void*)_ptr, _name, _size); \
  100. } while (0)
  101. /* nsCOMPtr.h allows these macros to be defined by clients
  102. * These logging functions require dynamic_cast<void*>, so they don't
  103. * do anything useful if we don't have dynamic_cast<void*>.
  104. * Note: The explicit comparison to nullptr is needed to avoid warnings
  105. * when _p is a nullptr itself. */
  106. #define NSCAP_LOG_ASSIGNMENT(_c, _p) \
  107. if (_p != nullptr) \
  108. NS_LogCOMPtrAddRef((_c),static_cast<nsISupports*>(_p))
  109. #define NSCAP_LOG_RELEASE(_c, _p) \
  110. if (_p) \
  111. NS_LogCOMPtrRelease((_c), static_cast<nsISupports*>(_p))
  112. #else /* !NS_BUILD_REFCNT_LOGGING */
  113. #define NS_LOG_ADDREF(_p, _rc, _type, _size)
  114. #define NS_LOG_RELEASE(_p, _rc, _type)
  115. #define MOZ_COUNT_CTOR(_type)
  116. #define MOZ_COUNT_CTOR_INHERITED(_type, _base)
  117. #define MOZ_LOG_CTOR(_ptr, _name, _size)
  118. #define MOZ_COUNT_DTOR(_type)
  119. #define MOZ_COUNT_DTOR_INHERITED(_type, _base)
  120. #define MOZ_LOG_DTOR(_ptr, _name, _size)
  121. #endif /* NS_BUILD_REFCNT_LOGGING */
  122. // Support for ISupports classes which interact with cycle collector.
  123. #define NS_NUMBER_OF_FLAGS_IN_REFCNT 2
  124. #define NS_IN_PURPLE_BUFFER (1 << 0)
  125. #define NS_IS_PURPLE (1 << 1)
  126. #define NS_REFCOUNT_CHANGE (1 << NS_NUMBER_OF_FLAGS_IN_REFCNT)
  127. #define NS_REFCOUNT_VALUE(_val) (_val >> NS_NUMBER_OF_FLAGS_IN_REFCNT)
  128. class nsCycleCollectingAutoRefCnt
  129. {
  130. public:
  131. nsCycleCollectingAutoRefCnt() : mRefCntAndFlags(0) {}
  132. explicit nsCycleCollectingAutoRefCnt(uintptr_t aValue)
  133. : mRefCntAndFlags(aValue << NS_NUMBER_OF_FLAGS_IN_REFCNT)
  134. {
  135. }
  136. nsCycleCollectingAutoRefCnt(const nsCycleCollectingAutoRefCnt&) = delete;
  137. void operator=(const nsCycleCollectingAutoRefCnt&) = delete;
  138. MOZ_ALWAYS_INLINE uintptr_t incr(nsISupports* aOwner)
  139. {
  140. return incr(aOwner, nullptr);
  141. }
  142. MOZ_ALWAYS_INLINE uintptr_t incr(void* aOwner,
  143. nsCycleCollectionParticipant* aCp)
  144. {
  145. mRefCntAndFlags += NS_REFCOUNT_CHANGE;
  146. mRefCntAndFlags &= ~NS_IS_PURPLE;
  147. // For incremental cycle collection, use the purple buffer to track objects
  148. // that have been AddRef'd.
  149. if (!IsInPurpleBuffer()) {
  150. mRefCntAndFlags |= NS_IN_PURPLE_BUFFER;
  151. // Refcount isn't zero, so Suspect won't delete anything.
  152. MOZ_ASSERT(get() > 0);
  153. NS_CycleCollectorSuspect3(aOwner, aCp, this, nullptr);
  154. }
  155. return NS_REFCOUNT_VALUE(mRefCntAndFlags);
  156. }
  157. MOZ_ALWAYS_INLINE void stabilizeForDeletion()
  158. {
  159. // Set refcnt to 1 and mark us to be in the purple buffer.
  160. // This way decr won't call suspect again.
  161. mRefCntAndFlags = NS_REFCOUNT_CHANGE | NS_IN_PURPLE_BUFFER;
  162. }
  163. MOZ_ALWAYS_INLINE uintptr_t decr(nsISupports* aOwner,
  164. bool* aShouldDelete = nullptr)
  165. {
  166. return decr(aOwner, nullptr, aShouldDelete);
  167. }
  168. MOZ_ALWAYS_INLINE uintptr_t decr(void* aOwner,
  169. nsCycleCollectionParticipant* aCp,
  170. bool* aShouldDelete = nullptr)
  171. {
  172. MOZ_ASSERT(get() > 0);
  173. if (!IsInPurpleBuffer()) {
  174. mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
  175. mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
  176. uintptr_t retval = NS_REFCOUNT_VALUE(mRefCntAndFlags);
  177. // Suspect may delete 'aOwner' and 'this'!
  178. NS_CycleCollectorSuspect3(aOwner, aCp, this, aShouldDelete);
  179. return retval;
  180. }
  181. mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
  182. mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
  183. return NS_REFCOUNT_VALUE(mRefCntAndFlags);
  184. }
  185. MOZ_ALWAYS_INLINE void RemovePurple()
  186. {
  187. MOZ_ASSERT(IsPurple(), "must be purple");
  188. mRefCntAndFlags &= ~NS_IS_PURPLE;
  189. }
  190. MOZ_ALWAYS_INLINE void RemoveFromPurpleBuffer()
  191. {
  192. MOZ_ASSERT(IsInPurpleBuffer());
  193. mRefCntAndFlags &= ~(NS_IS_PURPLE | NS_IN_PURPLE_BUFFER);
  194. }
  195. MOZ_ALWAYS_INLINE bool IsPurple() const
  196. {
  197. return !!(mRefCntAndFlags & NS_IS_PURPLE);
  198. }
  199. MOZ_ALWAYS_INLINE bool IsInPurpleBuffer() const
  200. {
  201. return !!(mRefCntAndFlags & NS_IN_PURPLE_BUFFER);
  202. }
  203. MOZ_ALWAYS_INLINE nsrefcnt get() const
  204. {
  205. return NS_REFCOUNT_VALUE(mRefCntAndFlags);
  206. }
  207. MOZ_ALWAYS_INLINE operator nsrefcnt() const
  208. {
  209. return get();
  210. }
  211. private:
  212. uintptr_t mRefCntAndFlags;
  213. };
  214. class nsAutoRefCnt
  215. {
  216. public:
  217. nsAutoRefCnt() : mValue(0) {}
  218. explicit nsAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
  219. nsAutoRefCnt(const nsAutoRefCnt&) = delete;
  220. void operator=(const nsAutoRefCnt&) = delete;
  221. // only support prefix increment/decrement
  222. nsrefcnt operator++() { return ++mValue; }
  223. nsrefcnt operator--() { return --mValue; }
  224. nsrefcnt operator=(nsrefcnt aValue) { return (mValue = aValue); }
  225. operator nsrefcnt() const { return mValue; }
  226. nsrefcnt get() const { return mValue; }
  227. static const bool isThreadSafe = false;
  228. private:
  229. nsrefcnt operator++(int) = delete;
  230. nsrefcnt operator--(int) = delete;
  231. nsrefcnt mValue;
  232. };
  233. namespace mozilla {
  234. class ThreadSafeAutoRefCnt
  235. {
  236. public:
  237. ThreadSafeAutoRefCnt() : mValue(0) {}
  238. explicit ThreadSafeAutoRefCnt(nsrefcnt aValue) : mValue(aValue) {}
  239. ThreadSafeAutoRefCnt(const ThreadSafeAutoRefCnt&) = delete;
  240. void operator=(const ThreadSafeAutoRefCnt&) = delete;
  241. // only support prefix increment/decrement
  242. MOZ_ALWAYS_INLINE nsrefcnt operator++() { return ++mValue; }
  243. MOZ_ALWAYS_INLINE nsrefcnt operator--() { return --mValue; }
  244. MOZ_ALWAYS_INLINE nsrefcnt operator=(nsrefcnt aValue)
  245. {
  246. return (mValue = aValue);
  247. }
  248. MOZ_ALWAYS_INLINE operator nsrefcnt() const { return mValue; }
  249. MOZ_ALWAYS_INLINE nsrefcnt get() const { return mValue; }
  250. static const bool isThreadSafe = true;
  251. private:
  252. nsrefcnt operator++(int) = delete;
  253. nsrefcnt operator--(int) = delete;
  254. // In theory, RelaseAcquire consistency (but no weaker) is sufficient for
  255. // the counter. Making it weaker could speed up builds on ARM (but not x86),
  256. // but could break pre-existing code that assumes sequential consistency.
  257. Atomic<nsrefcnt> mValue;
  258. };
  259. } // namespace mozilla
  260. ///////////////////////////////////////////////////////////////////////////////
  261. /**
  262. * Declare the reference count variable and the implementations of the
  263. * AddRef and QueryInterface methods.
  264. */
  265. #define NS_DECL_ISUPPORTS \
  266. public: \
  267. NS_IMETHOD QueryInterface(REFNSIID aIID, \
  268. void** aInstancePtr) override; \
  269. NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override; \
  270. NS_IMETHOD_(MozExternalRefCountType) Release(void) override; \
  271. typedef mozilla::FalseType HasThreadSafeRefCnt; \
  272. protected: \
  273. nsAutoRefCnt mRefCnt; \
  274. NS_DECL_OWNINGTHREAD \
  275. public:
  276. #define NS_DECL_THREADSAFE_ISUPPORTS \
  277. public: \
  278. NS_IMETHOD QueryInterface(REFNSIID aIID, \
  279. void** aInstancePtr) override; \
  280. NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override; \
  281. NS_IMETHOD_(MozExternalRefCountType) Release(void) override; \
  282. typedef mozilla::TrueType HasThreadSafeRefCnt; \
  283. protected: \
  284. ::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
  285. NS_DECL_OWNINGTHREAD \
  286. public:
  287. #define NS_DECL_CYCLE_COLLECTING_ISUPPORTS \
  288. public: \
  289. NS_IMETHOD QueryInterface(REFNSIID aIID, \
  290. void** aInstancePtr) override; \
  291. NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override; \
  292. NS_IMETHOD_(MozExternalRefCountType) Release(void) override; \
  293. NS_IMETHOD_(void) DeleteCycleCollectable(void); \
  294. typedef mozilla::FalseType HasThreadSafeRefCnt; \
  295. protected: \
  296. nsCycleCollectingAutoRefCnt mRefCnt; \
  297. NS_DECL_OWNINGTHREAD \
  298. public:
  299. ///////////////////////////////////////////////////////////////////////////////
  300. /*
  301. * Implementation of AddRef and Release for non-nsISupports (ie "native")
  302. * cycle-collected classes that use the purple buffer to avoid leaks.
  303. */
  304. #define NS_IMPL_CC_NATIVE_ADDREF_BODY(_class) \
  305. MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
  306. MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
  307. NS_ASSERT_OWNINGTHREAD(_class); \
  308. nsrefcnt count = \
  309. mRefCnt.incr(static_cast<void*>(this), \
  310. _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
  311. NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
  312. return count;
  313. #define NS_IMPL_CC_NATIVE_RELEASE_BODY(_class) \
  314. MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
  315. NS_ASSERT_OWNINGTHREAD(_class); \
  316. nsrefcnt count = \
  317. mRefCnt.decr(static_cast<void*>(this), \
  318. _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
  319. NS_LOG_RELEASE(this, count, #_class); \
  320. return count;
  321. #define NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(_class) \
  322. NS_METHOD_(MozExternalRefCountType) _class::AddRef(void) \
  323. { \
  324. NS_IMPL_CC_NATIVE_ADDREF_BODY(_class) \
  325. }
  326. #define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE_WITH_LAST_RELEASE(_class, _last) \
  327. NS_METHOD_(MozExternalRefCountType) _class::Release(void) \
  328. { \
  329. MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
  330. NS_ASSERT_OWNINGTHREAD(_class); \
  331. bool shouldDelete = false; \
  332. nsrefcnt count = \
  333. mRefCnt.decr(static_cast<void*>(this), \
  334. _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant(), \
  335. &shouldDelete); \
  336. NS_LOG_RELEASE(this, count, #_class); \
  337. if (count == 0) { \
  338. mRefCnt.incr(static_cast<void*>(this), \
  339. _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
  340. _last; \
  341. mRefCnt.decr(static_cast<void*>(this), \
  342. _class::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant()); \
  343. if (shouldDelete) { \
  344. mRefCnt.stabilizeForDeletion(); \
  345. DeleteCycleCollectable(); \
  346. } \
  347. } \
  348. return count; \
  349. }
  350. #define NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(_class) \
  351. NS_METHOD_(MozExternalRefCountType) _class::Release(void) \
  352. { \
  353. NS_IMPL_CC_NATIVE_RELEASE_BODY(_class) \
  354. }
  355. #define NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(_class) \
  356. public: \
  357. NS_METHOD_(MozExternalRefCountType) AddRef(void) { \
  358. NS_IMPL_CC_NATIVE_ADDREF_BODY(_class) \
  359. } \
  360. NS_METHOD_(MozExternalRefCountType) Release(void) { \
  361. NS_IMPL_CC_NATIVE_RELEASE_BODY(_class) \
  362. } \
  363. typedef mozilla::FalseType HasThreadSafeRefCnt; \
  364. protected: \
  365. nsCycleCollectingAutoRefCnt mRefCnt; \
  366. NS_DECL_OWNINGTHREAD \
  367. public:
  368. ///////////////////////////////////////////////////////////////////////////////
  369. /**
  370. * Use this macro to declare and implement the AddRef & Release methods for a
  371. * given non-XPCOM <i>_class</i>.
  372. *
  373. * @param _class The name of the class implementing the method
  374. * @param _destroy A statement that is executed when the object's
  375. * refcount drops to zero.
  376. * @param optional override Mark the AddRef & Release methods as overrides.
  377. */
  378. #define NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, _destroy, ...) \
  379. public: \
  380. NS_METHOD_(MozExternalRefCountType) AddRef(void) __VA_ARGS__ { \
  381. MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
  382. MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
  383. NS_ASSERT_OWNINGTHREAD(_class); \
  384. ++mRefCnt; \
  385. NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this)); \
  386. return mRefCnt; \
  387. } \
  388. NS_METHOD_(MozExternalRefCountType) Release(void) __VA_ARGS__ { \
  389. MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
  390. NS_ASSERT_OWNINGTHREAD(_class); \
  391. --mRefCnt; \
  392. NS_LOG_RELEASE(this, mRefCnt, #_class); \
  393. if (mRefCnt == 0) { \
  394. mRefCnt = 1; /* stabilize */ \
  395. _destroy; \
  396. return 0; \
  397. } \
  398. return mRefCnt; \
  399. } \
  400. typedef mozilla::FalseType HasThreadSafeRefCnt; \
  401. protected: \
  402. nsAutoRefCnt mRefCnt; \
  403. NS_DECL_OWNINGTHREAD \
  404. public:
  405. /**
  406. * Use this macro to declare and implement the AddRef & Release methods for a
  407. * given non-XPCOM <i>_class</i>.
  408. *
  409. * @param _class The name of the class implementing the method
  410. * @param optional override Mark the AddRef & Release methods as overrides.
  411. */
  412. #define NS_INLINE_DECL_REFCOUNTING(_class, ...) \
  413. NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, delete(this), __VA_ARGS__)
  414. #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, _decl, ...) \
  415. public: \
  416. _decl(MozExternalRefCountType) AddRef(void) __VA_ARGS__ { \
  417. MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
  418. MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
  419. nsrefcnt count = ++mRefCnt; \
  420. NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
  421. return (nsrefcnt) count; \
  422. } \
  423. _decl(MozExternalRefCountType) Release(void) __VA_ARGS__ { \
  424. MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
  425. nsrefcnt count = --mRefCnt; \
  426. NS_LOG_RELEASE(this, count, #_class); \
  427. if (count == 0) { \
  428. delete (this); \
  429. return 0; \
  430. } \
  431. return count; \
  432. } \
  433. typedef mozilla::TrueType HasThreadSafeRefCnt; \
  434. protected: \
  435. ::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
  436. public:
  437. /**
  438. * Use this macro to declare and implement the AddRef & Release methods for a
  439. * given non-XPCOM <i>_class</i> in a threadsafe manner.
  440. *
  441. * DOES NOT DO REFCOUNT STABILIZATION!
  442. *
  443. * @param _class The name of the class implementing the method
  444. */
  445. #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING(_class, ...) \
  446. NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_METHOD_, __VA_ARGS__)
  447. /**
  448. * Like NS_INLINE_DECL_THREADSAFE_REFCOUNTING with AddRef & Release declared
  449. * virtual.
  450. */
  451. #define NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING(_class, ...) \
  452. NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, NS_IMETHOD_, __VA_ARGS__)
  453. /**
  454. * Use this macro to implement the AddRef method for a given <i>_class</i>
  455. * @param _class The name of the class implementing the method
  456. */
  457. #define NS_IMPL_ADDREF(_class) \
  458. NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void) \
  459. { \
  460. MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
  461. MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
  462. if (!mRefCnt.isThreadSafe) \
  463. NS_ASSERT_OWNINGTHREAD(_class); \
  464. nsrefcnt count = ++mRefCnt; \
  465. NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
  466. return count; \
  467. }
  468. /**
  469. * Use this macro to implement the AddRef method for a given <i>_class</i>
  470. * implemented as a wholly owned aggregated object intended to implement
  471. * interface(s) for its owner
  472. * @param _class The name of the class implementing the method
  473. * @param _aggregator the owning/containing object
  474. */
  475. #define NS_IMPL_ADDREF_USING_AGGREGATOR(_class, _aggregator) \
  476. NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void) \
  477. { \
  478. MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
  479. NS_PRECONDITION(_aggregator, "null aggregator"); \
  480. return (_aggregator)->AddRef(); \
  481. }
  482. /**
  483. * Use this macro to implement the Release method for a given
  484. * <i>_class</i>.
  485. * @param _class The name of the class implementing the method
  486. * @param _destroy A statement that is executed when the object's
  487. * refcount drops to zero.
  488. *
  489. * For example,
  490. *
  491. * NS_IMPL_RELEASE_WITH_DESTROY(Foo, Destroy(this))
  492. *
  493. * will cause
  494. *
  495. * Destroy(this);
  496. *
  497. * to be invoked when the object's refcount drops to zero. This
  498. * allows for arbitrary teardown activity to occur (e.g., deallocation
  499. * of object allocated with placement new).
  500. */
  501. #define NS_IMPL_RELEASE_WITH_DESTROY(_class, _destroy) \
  502. NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \
  503. { \
  504. MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
  505. if (!mRefCnt.isThreadSafe) \
  506. NS_ASSERT_OWNINGTHREAD(_class); \
  507. nsrefcnt count = --mRefCnt; \
  508. NS_LOG_RELEASE(this, count, #_class); \
  509. if (count == 0) { \
  510. mRefCnt = 1; /* stabilize */ \
  511. _destroy; \
  512. return 0; \
  513. } \
  514. return count; \
  515. }
  516. /**
  517. * Use this macro to implement the Release method for a given <i>_class</i>
  518. * @param _class The name of the class implementing the method
  519. *
  520. * A note on the 'stabilization' of the refcnt to one. At that point,
  521. * the object's refcount will have gone to zero. The object's
  522. * destructor may trigger code that attempts to QueryInterface() and
  523. * Release() 'this' again. Doing so will temporarily increment and
  524. * decrement the refcount. (Only a logic error would make one try to
  525. * keep a permanent hold on 'this'.) To prevent re-entering the
  526. * destructor, we make sure that no balanced refcounting can return
  527. * the refcount to |0|.
  528. */
  529. #define NS_IMPL_RELEASE(_class) \
  530. NS_IMPL_RELEASE_WITH_DESTROY(_class, delete (this))
  531. /**
  532. * Use this macro to implement the Release method for a given <i>_class</i>
  533. * implemented as a wholly owned aggregated object intended to implement
  534. * interface(s) for its owner
  535. * @param _class The name of the class implementing the method
  536. * @param _aggregator the owning/containing object
  537. */
  538. #define NS_IMPL_RELEASE_USING_AGGREGATOR(_class, _aggregator) \
  539. NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \
  540. { \
  541. NS_PRECONDITION(_aggregator, "null aggregator"); \
  542. return (_aggregator)->Release(); \
  543. }
  544. #define NS_IMPL_CYCLE_COLLECTING_ADDREF(_class) \
  545. NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void) \
  546. { \
  547. MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
  548. MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
  549. NS_ASSERT_OWNINGTHREAD(_class); \
  550. nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
  551. nsrefcnt count = mRefCnt.incr(base); \
  552. NS_LOG_ADDREF(this, count, #_class, sizeof(*this)); \
  553. return count; \
  554. }
  555. #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, _destroy) \
  556. NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \
  557. { \
  558. MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
  559. NS_ASSERT_OWNINGTHREAD(_class); \
  560. nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
  561. nsrefcnt count = mRefCnt.decr(base); \
  562. NS_LOG_RELEASE(this, count, #_class); \
  563. return count; \
  564. } \
  565. NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void) \
  566. { \
  567. _destroy; \
  568. }
  569. #define NS_IMPL_CYCLE_COLLECTING_RELEASE(_class) \
  570. NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, delete (this))
  571. // _LAST_RELEASE can be useful when certain resources should be released
  572. // as soon as we know the object will be deleted.
  573. #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(_class, _last) \
  574. NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void) \
  575. { \
  576. MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
  577. NS_ASSERT_OWNINGTHREAD(_class); \
  578. bool shouldDelete = false; \
  579. nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
  580. nsrefcnt count = mRefCnt.decr(base, &shouldDelete); \
  581. NS_LOG_RELEASE(this, count, #_class); \
  582. if (count == 0) { \
  583. mRefCnt.incr(base); \
  584. _last; \
  585. mRefCnt.decr(base); \
  586. if (shouldDelete) { \
  587. mRefCnt.stabilizeForDeletion(); \
  588. DeleteCycleCollectable(); \
  589. } \
  590. } \
  591. return count; \
  592. } \
  593. NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void) \
  594. { \
  595. delete this; \
  596. }
  597. ///////////////////////////////////////////////////////////////////////////////
  598. /**
  599. * There are two ways of implementing QueryInterface, and we use both:
  600. *
  601. * Table-driven QueryInterface uses a static table of IID->offset mappings
  602. * and a shared helper function. Using it tends to reduce codesize and improve
  603. * runtime performance (due to processor cache hits).
  604. *
  605. * Macro-driven QueryInterface generates a QueryInterface function directly
  606. * using common macros. This is necessary if special QueryInterface features
  607. * are being used (such as tearoffs and conditional interfaces).
  608. *
  609. * These methods can be combined into a table-driven function call followed
  610. * by custom code for tearoffs and conditionals.
  611. */
  612. struct QITableEntry
  613. {
  614. const nsIID* iid; // null indicates end of the QITableEntry array
  615. int32_t offset;
  616. };
  617. nsresult NS_FASTCALL
  618. NS_TableDrivenQI(void* aThis, REFNSIID aIID,
  619. void** aInstancePtr, const QITableEntry* aEntries);
  620. /**
  621. * Implement table-driven queryinterface
  622. */
  623. #define NS_INTERFACE_TABLE_HEAD(_class) \
  624. NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
  625. { \
  626. NS_ASSERTION(aInstancePtr, \
  627. "QueryInterface requires a non-NULL destination!"); \
  628. nsresult rv = NS_ERROR_FAILURE;
  629. #define NS_INTERFACE_TABLE_BEGIN \
  630. static const QITableEntry table[] = {
  631. #define NS_INTERFACE_TABLE_ENTRY(_class, _interface) \
  632. { &NS_GET_IID(_interface), \
  633. int32_t(reinterpret_cast<char*>( \
  634. static_cast<_interface*>((_class*) 0x1000)) - \
  635. reinterpret_cast<char*>((_class*) 0x1000)) \
  636. },
  637. #define NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, _interface, _implClass) \
  638. { &NS_GET_IID(_interface), \
  639. int32_t(reinterpret_cast<char*>( \
  640. static_cast<_interface*>( \
  641. static_cast<_implClass*>( \
  642. (_class*) 0x1000))) - \
  643. reinterpret_cast<char*>((_class*) 0x1000)) \
  644. },
  645. /*
  646. * XXX: we want to use mozilla::ArrayLength (or equivalent,
  647. * MOZ_ARRAY_LENGTH) in this condition, but some versions of GCC don't
  648. * see that the static_assert condition is actually constant in those
  649. * cases, even with constexpr support (?).
  650. */
  651. #define NS_INTERFACE_TABLE_END_WITH_PTR(_ptr) \
  652. { nullptr, 0 } }; \
  653. static_assert((sizeof(table)/sizeof(table[0])) > 1, "need at least 1 interface"); \
  654. rv = NS_TableDrivenQI(static_cast<void*>(_ptr), \
  655. aIID, aInstancePtr, table);
  656. #define NS_INTERFACE_TABLE_END \
  657. NS_INTERFACE_TABLE_END_WITH_PTR(this)
  658. #define NS_INTERFACE_TABLE_TAIL \
  659. return rv; \
  660. }
  661. #define NS_INTERFACE_TABLE_TAIL_INHERITING(_baseclass) \
  662. if (NS_SUCCEEDED(rv)) \
  663. return rv; \
  664. return _baseclass::QueryInterface(aIID, aInstancePtr); \
  665. }
  666. #define NS_INTERFACE_TABLE_TAIL_USING_AGGREGATOR(_aggregator) \
  667. if (NS_SUCCEEDED(rv)) \
  668. return rv; \
  669. NS_ASSERTION(_aggregator, "null aggregator"); \
  670. return _aggregator->QueryInterface(aIID, aInstancePtr) \
  671. }
  672. /**
  673. * This implements query interface with two assumptions: First, the
  674. * class in question implements nsISupports and its own interface and
  675. * nothing else. Second, the implementation of the class's primary
  676. * inheritance chain leads to its own interface.
  677. *
  678. * @param _class The name of the class implementing the method
  679. * @param _classiiddef The name of the #define symbol that defines the IID
  680. * for the class (e.g. NS_ISUPPORTS_IID)
  681. */
  682. #define NS_IMPL_QUERY_HEAD(_class) \
  683. NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
  684. { \
  685. NS_ASSERTION(aInstancePtr, \
  686. "QueryInterface requires a non-NULL destination!"); \
  687. nsISupports* foundInterface;
  688. #define NS_IMPL_QUERY_BODY(_interface) \
  689. if ( aIID.Equals(NS_GET_IID(_interface)) ) \
  690. foundInterface = static_cast<_interface*>(this); \
  691. else
  692. #define NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition) \
  693. if ( (condition) && aIID.Equals(NS_GET_IID(_interface))) \
  694. foundInterface = static_cast<_interface*>(this); \
  695. else
  696. #define NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass) \
  697. if ( aIID.Equals(NS_GET_IID(_interface)) ) \
  698. foundInterface = static_cast<_interface*>( \
  699. static_cast<_implClass*>(this)); \
  700. else
  701. #define NS_IMPL_QUERY_BODY_AGGREGATED(_interface, _aggregate) \
  702. if ( aIID.Equals(NS_GET_IID(_interface)) ) \
  703. foundInterface = static_cast<_interface*>(_aggregate); \
  704. else
  705. #define NS_IMPL_QUERY_TAIL_GUTS \
  706. foundInterface = 0; \
  707. nsresult status; \
  708. if ( !foundInterface ) \
  709. { \
  710. /* nsISupports should be handled by this point. If not, fail. */ \
  711. MOZ_ASSERT(!aIID.Equals(NS_GET_IID(nsISupports))); \
  712. status = NS_NOINTERFACE; \
  713. } \
  714. else \
  715. { \
  716. NS_ADDREF(foundInterface); \
  717. status = NS_OK; \
  718. } \
  719. *aInstancePtr = foundInterface; \
  720. return status; \
  721. }
  722. #define NS_IMPL_QUERY_TAIL_INHERITING(_baseclass) \
  723. foundInterface = 0; \
  724. nsresult status; \
  725. if ( !foundInterface ) \
  726. status = _baseclass::QueryInterface(aIID, (void**)&foundInterface); \
  727. else \
  728. { \
  729. NS_ADDREF(foundInterface); \
  730. status = NS_OK; \
  731. } \
  732. *aInstancePtr = foundInterface; \
  733. return status; \
  734. }
  735. #define NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator) \
  736. foundInterface = 0; \
  737. nsresult status; \
  738. if ( !foundInterface ) { \
  739. NS_ASSERTION(_aggregator, "null aggregator"); \
  740. status = _aggregator->QueryInterface(aIID, (void**)&foundInterface); \
  741. } else \
  742. { \
  743. NS_ADDREF(foundInterface); \
  744. status = NS_OK; \
  745. } \
  746. *aInstancePtr = foundInterface; \
  747. return status; \
  748. }
  749. #define NS_IMPL_QUERY_TAIL(_supports_interface) \
  750. NS_IMPL_QUERY_BODY_AMBIGUOUS(nsISupports, _supports_interface) \
  751. NS_IMPL_QUERY_TAIL_GUTS
  752. /*
  753. This is the new scheme. Using this notation now will allow us to switch to
  754. a table driven mechanism when it's ready. Note the difference between this
  755. and the (currently) underlying NS_IMPL_QUERY_INTERFACE mechanism. You must
  756. explicitly mention |nsISupports| when using the interface maps.
  757. */
  758. #define NS_INTERFACE_MAP_BEGIN(_implClass) NS_IMPL_QUERY_HEAD(_implClass)
  759. #define NS_INTERFACE_MAP_ENTRY(_interface) NS_IMPL_QUERY_BODY(_interface)
  760. #define NS_INTERFACE_MAP_ENTRY_CONDITIONAL(_interface, condition) \
  761. NS_IMPL_QUERY_BODY_CONDITIONAL(_interface, condition)
  762. #define NS_INTERFACE_MAP_ENTRY_AGGREGATED(_interface,_aggregate) \
  763. NS_IMPL_QUERY_BODY_AGGREGATED(_interface,_aggregate)
  764. #define NS_INTERFACE_MAP_END NS_IMPL_QUERY_TAIL_GUTS
  765. #define NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(_interface, _implClass) \
  766. NS_IMPL_QUERY_BODY_AMBIGUOUS(_interface, _implClass)
  767. #define NS_INTERFACE_MAP_END_INHERITING(_baseClass) \
  768. NS_IMPL_QUERY_TAIL_INHERITING(_baseClass)
  769. #define NS_INTERFACE_MAP_END_AGGREGATED(_aggregator) \
  770. NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)
  771. #define NS_INTERFACE_TABLE0(_class) \
  772. NS_INTERFACE_TABLE_BEGIN \
  773. NS_INTERFACE_TABLE_ENTRY(_class, nsISupports) \
  774. NS_INTERFACE_TABLE_END
  775. #define NS_INTERFACE_TABLE(aClass, ...) \
  776. MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
  777. NS_INTERFACE_TABLE_BEGIN \
  778. MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \
  779. NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(aClass, nsISupports, \
  780. MOZ_ARG_1(__VA_ARGS__)) \
  781. NS_INTERFACE_TABLE_END
  782. #define NS_IMPL_QUERY_INTERFACE0(_class) \
  783. NS_INTERFACE_TABLE_HEAD(_class) \
  784. NS_INTERFACE_TABLE0(_class) \
  785. NS_INTERFACE_TABLE_TAIL
  786. #define NS_IMPL_QUERY_INTERFACE(aClass, ...) \
  787. NS_INTERFACE_TABLE_HEAD(aClass) \
  788. NS_INTERFACE_TABLE(aClass, __VA_ARGS__) \
  789. NS_INTERFACE_TABLE_TAIL
  790. /**
  791. * Declare that you're going to inherit from something that already
  792. * implements nsISupports, but also implements an additional interface, thus
  793. * causing an ambiguity. In this case you don't need another mRefCnt, you
  794. * just need to forward the definitions to the appropriate superclass. E.g.
  795. *
  796. * class Bar : public Foo, public nsIBar { // both provide nsISupports
  797. * public:
  798. * NS_DECL_ISUPPORTS_INHERITED
  799. * ...other nsIBar and Bar methods...
  800. * };
  801. */
  802. #define NS_DECL_ISUPPORTS_INHERITED \
  803. public: \
  804. NS_IMETHOD QueryInterface(REFNSIID aIID, \
  805. void** aInstancePtr) override; \
  806. NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override; \
  807. NS_IMETHOD_(MozExternalRefCountType) Release(void) override; \
  808. /**
  809. * These macros can be used in conjunction with NS_DECL_ISUPPORTS_INHERITED
  810. * to implement the nsISupports methods, forwarding the invocations to a
  811. * superclass that already implements nsISupports.
  812. *
  813. * Note that I didn't make these inlined because they're virtual methods.
  814. */
  815. #define NS_IMPL_ADDREF_INHERITED(Class, Super) \
  816. NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void) \
  817. { \
  818. MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(Class) \
  819. nsrefcnt r = Super::AddRef(); \
  820. NS_LOG_ADDREF(this, r, #Class, sizeof(*this)); \
  821. return r; \
  822. }
  823. #define NS_IMPL_RELEASE_INHERITED(Class, Super) \
  824. NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \
  825. { \
  826. nsrefcnt r = Super::Release(); \
  827. NS_LOG_RELEASE(this, r, #Class); \
  828. return r; \
  829. }
  830. /**
  831. * As above but not logging the addref/release; needed if the base
  832. * class might be aggregated.
  833. */
  834. #define NS_IMPL_NONLOGGING_ADDREF_INHERITED(Class, Super) \
  835. NS_IMETHODIMP_(MozExternalRefCountType) Class::AddRef(void) \
  836. { \
  837. MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(Class) \
  838. return Super::AddRef(); \
  839. }
  840. #define NS_IMPL_NONLOGGING_RELEASE_INHERITED(Class, Super) \
  841. NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \
  842. { \
  843. return Super::Release(); \
  844. }
  845. #define NS_INTERFACE_TABLE_INHERITED0(Class) /* Nothing to do here */
  846. #define NS_INTERFACE_TABLE_INHERITED(aClass, ...) \
  847. MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
  848. NS_INTERFACE_TABLE_BEGIN \
  849. MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \
  850. NS_INTERFACE_TABLE_END
  851. #define NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, ...) \
  852. NS_INTERFACE_TABLE_HEAD(aClass) \
  853. NS_INTERFACE_TABLE_INHERITED(aClass, __VA_ARGS__) \
  854. NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)
  855. /**
  856. * Convenience macros for implementing all nsISupports methods for
  857. * a simple class.
  858. * @param _class The name of the class implementing the method
  859. * @param _classiiddef The name of the #define symbol that defines the IID
  860. * for the class (e.g. NS_ISUPPORTS_IID)
  861. */
  862. #define NS_IMPL_ISUPPORTS0(_class) \
  863. NS_IMPL_ADDREF(_class) \
  864. NS_IMPL_RELEASE(_class) \
  865. NS_IMPL_QUERY_INTERFACE0(_class)
  866. #define NS_IMPL_ISUPPORTS(aClass, ...) \
  867. NS_IMPL_ADDREF(aClass) \
  868. NS_IMPL_RELEASE(aClass) \
  869. NS_IMPL_QUERY_INTERFACE(aClass, __VA_ARGS__)
  870. #define NS_IMPL_ISUPPORTS_INHERITED0(aClass, aSuper) \
  871. NS_INTERFACE_TABLE_HEAD(aClass) \
  872. NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper) \
  873. NS_IMPL_ADDREF_INHERITED(aClass, aSuper) \
  874. NS_IMPL_RELEASE_INHERITED(aClass, aSuper) \
  875. #define NS_IMPL_ISUPPORTS_INHERITED(aClass, aSuper, ...) \
  876. NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, __VA_ARGS__) \
  877. NS_IMPL_ADDREF_INHERITED(aClass, aSuper) \
  878. NS_IMPL_RELEASE_INHERITED(aClass, aSuper)
  879. /*
  880. * Macro to glue together a QI that starts with an interface table
  881. * and segues into an interface map (e.g. it uses singleton classinfo
  882. * or tearoffs).
  883. */
  884. #define NS_INTERFACE_TABLE_TO_MAP_SEGUE \
  885. if (rv == NS_OK) return rv; \
  886. nsISupports* foundInterface;
  887. ///////////////////////////////////////////////////////////////////////////////
  888. /**
  889. *
  890. * Threadsafe implementations of the ISupports convenience macros.
  891. *
  892. * @note These are not available when linking against the standalone glue,
  893. * because the implementation requires PR_ symbols.
  894. */
  895. #define NS_INTERFACE_MAP_END_THREADSAFE NS_IMPL_QUERY_TAIL_GUTS
  896. /**
  897. * Macro to generate nsIClassInfo methods for classes which do not have
  898. * corresponding nsIFactory implementations.
  899. */
  900. #define NS_IMPL_THREADSAFE_CI(_class) \
  901. NS_IMETHODIMP \
  902. _class::GetInterfaces(uint32_t* _count, nsIID*** _array) \
  903. { \
  904. return NS_CI_INTERFACE_GETTER_NAME(_class)(_count, _array); \
  905. } \
  906. \
  907. NS_IMETHODIMP \
  908. _class::GetScriptableHelper(nsIXPCScriptable** _retval) \
  909. { \
  910. *_retval = nullptr; \
  911. return NS_OK; \
  912. } \
  913. \
  914. NS_IMETHODIMP \
  915. _class::GetContractID(char** _contractID) \
  916. { \
  917. *_contractID = nullptr; \
  918. return NS_OK; \
  919. } \
  920. \
  921. NS_IMETHODIMP \
  922. _class::GetClassDescription(char** _classDescription) \
  923. { \
  924. *_classDescription = nullptr; \
  925. return NS_OK; \
  926. } \
  927. \
  928. NS_IMETHODIMP \
  929. _class::GetClassID(nsCID** _classID) \
  930. { \
  931. *_classID = nullptr; \
  932. return NS_OK; \
  933. } \
  934. \
  935. NS_IMETHODIMP \
  936. _class::GetFlags(uint32_t* _flags) \
  937. { \
  938. *_flags = nsIClassInfo::THREADSAFE; \
  939. return NS_OK; \
  940. } \
  941. \
  942. NS_IMETHODIMP \
  943. _class::GetClassIDNoAlloc(nsCID* _classIDNoAlloc) \
  944. { \
  945. return NS_ERROR_NOT_AVAILABLE; \
  946. }
  947. #endif