LCOV - code coverage report
Current view: top level - xpcom/base - nsISupportsImpl.h (source / functions) Hit Total Coverage
Test: output.info Lines: 59 71 83.1 %
Date: 2017-07-14 16:53:18 Functions: 64 80 80.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13