xpcom/base/nsAgg.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     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/. */
     6 #ifndef nsAgg_h___
     7 #define nsAgg_h___
     9 #include "nsISupports.h"
    10 #include "nsCycleCollectionParticipant.h"
    13 ////////////////////////////////////////////////////////////////////////////////
    15 // Put NS_DECL_AGGREGATED or NS_DECL_CYCLE_COLLECTING_AGGREGATED in your class's
    16 // declaration.
    17 #define NS_DECL_AGGREGATED                                                  \
    18     NS_DECL_ISUPPORTS                                                       \
    19     NS_DECL_AGGREGATED_HELPER
    21 #define NS_DECL_CYCLE_COLLECTING_AGGREGATED                                 \
    22     NS_DECL_CYCLE_COLLECTING_ISUPPORTS                                      \
    23     NS_DECL_AGGREGATED_HELPER
    25 #define NS_DECL_AGGREGATED_HELPER                                           \
    26 public:                                                                     \
    27                                                                             \
    28     /**                                                                     \
    29      * Returns the nsISupports pointer of the inner object (aka the         \
    30      * aggregatee). This pointer is really only useful to the outer object  \
    31      * (aka the aggregator), which can use it to hold on to the inner       \
    32      * object. Anything else wants the nsISupports pointer of the outer     \
    33      * object (gotten by QI'ing inner or outer to nsISupports). This method \
    34      * returns a non-addrefed pointer.                                      \
    35      * @return the nsISupports pointer of the inner object                  \
    36      */                                                                     \
    37     nsISupports* InnerObject(void) { return &fAggregated; }                 \
    38                                                                             \
    39     /**                                                                     \
    40      * Returns true if this object is part of an aggregated object.      \
    41      */                                                                     \
    42     bool IsPartOfAggregated(void) { return fOuter != InnerObject(); }     \
    43                                                                             \
    44 private:                                                                    \
    45                                                                             \
    46     /* You must implement this operation instead of the nsISupports */      \
    47     /* methods. */                                                          \
    48     nsresult                                                                \
    49     AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr);       \
    50                                                                             \
    51     class Internal : public nsISupports {                                   \
    52     public:                                                                 \
    53                                                                             \
    54         Internal() {}                                                       \
    55                                                                             \
    56         NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);  \
    57         NS_IMETHOD_(MozExternalRefCountType) AddRef(void);                  \
    58         NS_IMETHOD_(MozExternalRefCountType) Release(void);                 \
    59                                                                             \
    60         NS_DECL_OWNINGTHREAD                                                \
    61     };                                                                      \
    62                                                                             \
    63     friend class Internal;                                                  \
    64                                                                             \
    65     nsISupports*        fOuter;                                             \
    66     Internal            fAggregated;                                        \
    67                                                                             \
    68 public:                                                                     \
    70 #define NS_DECL_AGGREGATED_CYCLE_COLLECTION_CLASS(_class)                   \
    71 class NS_CYCLE_COLLECTION_INNERCLASS                                        \
    72  : public nsXPCOMCycleCollectionParticipant                                 \
    73 {                                                                           \
    74 public:                                                                     \
    75   NS_IMETHOD_(void) Unlink(void *p);                                        \
    76   NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);     \
    77   NS_IMETHOD_(void) DeleteCycleCollectable(void* p)                         \
    78   {                                                                         \
    79     NS_CYCLE_COLLECTION_CLASSNAME(_class)::                                 \
    80       Downcast(static_cast<nsISupports*>(p))->DeleteCycleCollectable();     \
    81   }                                                                         \
    82   static _class* Downcast(nsISupports* s)                                   \
    83   {                                                                         \
    84     return (_class*)((char*)(s) - offsetof(_class, fAggregated));           \
    85   }                                                                         \
    86   static nsISupports* Upcast(_class *p)                                     \
    87   {                                                                         \
    88     return p->InnerObject();                                                \
    89   }                                                                         \
    90   static nsXPCOMCycleCollectionParticipant* GetParticipant()                \
    91   {                                                                         \
    92     return &_class::NS_CYCLE_COLLECTION_INNERNAME;                          \
    93   }                                                                         \
    94 };                                                                          \
    95 NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(_class);                                \
    96 static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
    98 // Put this in your class's constructor:
    99 #define NS_INIT_AGGREGATED(outer)                                           \
   100   PR_BEGIN_MACRO                                                            \
   101     fOuter = outer ? outer : &fAggregated;                                  \
   102   PR_END_MACRO
   105 // Put this in your class's implementation file:
   106 #define NS_IMPL_AGGREGATED(_class)                                          \
   107                                                                             \
   108 NS_IMPL_AGGREGATED_HELPER(_class)                                           \
   109                                                                             \
   110 NS_IMETHODIMP_(MozExternalRefCountType)                                     \
   111 _class::Internal::AddRef(void)                                              \
   112 {                                                                           \
   113     _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
   114     MOZ_ASSERT(int32_t(agg->mRefCnt) >= 0, "illegal refcnt");               \
   115     NS_ASSERT_OWNINGTHREAD(_class);                                         \
   116     ++agg->mRefCnt;                                                         \
   117     NS_LOG_ADDREF(this, agg->mRefCnt, #_class, sizeof(*this));              \
   118     return agg->mRefCnt;                                                    \
   119 }                                                                           \
   120                                                                             \
   121 NS_IMETHODIMP_(MozExternalRefCountType)                                     \
   122 _class::Internal::Release(void)                                             \
   123 {                                                                           \
   124     _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
   125     MOZ_ASSERT(int32_t(agg->mRefCnt) > 0, "dup release");                   \
   126     NS_ASSERT_OWNINGTHREAD(_class);                                         \
   127     --agg->mRefCnt;                                                         \
   128     NS_LOG_RELEASE(this, agg->mRefCnt, #_class);                            \
   129     if (agg->mRefCnt == 0) {                                                \
   130         agg->mRefCnt = 1; /* stabilize */                                   \
   131         delete agg;                                                         \
   132         return 0;                                                           \
   133     }                                                                       \
   134     return agg->mRefCnt;                                                    \
   135 }                                                                           \
   137 #define NS_IMPL_CYCLE_COLLECTING_AGGREGATED(_class)                         \
   138                                                                             \
   139 NS_IMPL_AGGREGATED_HELPER(_class)                                           \
   140                                                                             \
   141 NS_IMETHODIMP_(MozExternalRefCountType)                                     \
   142 _class::Internal::AddRef(void)                                              \
   143 {                                                                           \
   144     _class* agg = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Downcast(this);    \
   145     MOZ_ASSERT(int32_t(agg->mRefCnt) >= 0, "illegal refcnt");               \
   146     NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class);                          \
   147     nsrefcnt count = agg->mRefCnt.incr(this);                               \
   148     NS_LOG_ADDREF(this, count, #_class, sizeof(*agg));                      \
   149     return count;                                                           \
   150 }                                                                           \
   151 NS_IMETHODIMP_(MozExternalRefCountType)                                     \
   152 _class::Internal::Release(void)                                             \
   153 {                                                                           \
   154     _class* agg = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Downcast(this);    \
   155     MOZ_ASSERT(int32_t(agg->mRefCnt) > 0, "dup release");                   \
   156     NS_ASSERT_OWNINGTHREAD_AGGREGATE(agg, _class);                          \
   157     nsrefcnt count = agg->mRefCnt.decr(this);                               \
   158     NS_LOG_RELEASE(this, count, #_class);                                   \
   159     return count;                                                           \
   160 }                                                                           \
   161 NS_IMETHODIMP_(void)                                                        \
   162 _class::DeleteCycleCollectable(void)                                        \
   163 {                                                                           \
   164   delete this;                                                              \
   165 }
   167 #define NS_IMPL_AGGREGATED_HELPER(_class)                                   \
   168 NS_IMETHODIMP                                                               \
   169 _class::QueryInterface(const nsIID& aIID, void** aInstancePtr)              \
   170 {                                                                           \
   171     return fOuter->QueryInterface(aIID, aInstancePtr);                      \
   172 }                                                                           \
   173                                                                             \
   174 NS_IMETHODIMP_(MozExternalRefCountType)                                     \
   175 _class::AddRef(void)                                                        \
   176 {                                                                           \
   177     return fOuter->AddRef();                                                \
   178 }                                                                           \
   179                                                                             \
   180 NS_IMETHODIMP_(MozExternalRefCountType)                                     \
   181 _class::Release(void)                                                       \
   182 {                                                                           \
   183     return fOuter->Release();                                               \
   184 }                                                                           \
   185                                                                             \
   186 NS_IMETHODIMP                                                               \
   187 _class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr)    \
   188 {                                                                           \
   189     _class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
   190     return agg->AggregatedQueryInterface(aIID, aInstancePtr);               \
   191 }                                                                           \
   193 /**
   194  * To make aggregated objects participate in cycle collection we need to enable
   195  * the outer object (aggregator) to traverse/unlink the objects held by the
   196  * inner object (the aggregatee). We can't just make the inner object QI'able to
   197  * NS_CYCLECOLLECTIONPARTICIPANT_IID, we don't want to return the inner object's
   198  * nsCycleCollectionParticipant for the outer object (which will happen if the
   199  * outer object doesn't participate in cycle collection itself).
   200  * NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID enables the outer object to get
   201  * the inner objects nsCycleCollectionParticipant.
   202  *
   203  * There are three cases:
   204  *   - No aggregation
   205  *     QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will return the inner
   206  *     object's nsCycleCollectionParticipant.
   207  *
   208  *   - Aggregation and outer object does not participate in cycle collection
   209  *     QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will not return anything.
   210  *
   211  *   - Aggregation and outer object does participate in cycle collection
   212  *     QI'ing to NS_CYCLECOLLECTIONPARTICIPANT_IID will return the outer
   213  *     object's nsCycleCollectionParticipant. The outer object's
   214  *     nsCycleCollectionParticipant can then QI the inner object to
   215  *     NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID to get the inner object's
   216  *     nsCycleCollectionParticipant, which it can use to traverse/unlink the
   217  *     objects reachable from the inner object.
   218  */
   219 #define NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID                        \
   220 {                                                                           \
   221     0x32889b7e,                                                             \
   222     0xe4fe,                                                                 \
   223     0x43f4,                                                                 \
   224     { 0x85, 0x31, 0xb5, 0x28, 0x23, 0xa2, 0xe9, 0xfc }                      \
   225 }
   227 /**
   228  * Just holds the IID so NS_GET_IID works.
   229  */
   230 class nsAggregatedCycleCollectionParticipant
   231 {
   232 public:
   233     NS_DECLARE_STATIC_IID_ACCESSOR(NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID)
   234 };
   236 NS_DEFINE_STATIC_IID_ACCESSOR(nsAggregatedCycleCollectionParticipant, 
   237                               NS_AGGREGATED_CYCLECOLLECTIONPARTICIPANT_IID)
   239 // for use with QI macros in nsISupportsUtils.h:
   241 #define NS_INTERFACE_MAP_BEGIN_AGGREGATED(_class)                           \
   242   NS_IMPL_AGGREGATED_QUERY_HEAD(_class)
   244 #define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class)          \
   245   NS_IMPL_QUERY_CYCLE_COLLECTION(_class)
   247 #define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION_AGGREGATED(_class)        \
   248   NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class)                \
   249   NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
   251 #define NS_IMPL_AGGREGATED_QUERY_HEAD(_class)                               \
   252 nsresult                                                                    \
   253 _class::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr)        \
   254 {                                                                           \
   255   NS_ASSERTION(aInstancePtr,                                                \
   256                "AggregatedQueryInterface requires a non-NULL result ptr!"); \
   257   if ( !aInstancePtr )                                                      \
   258     return NS_ERROR_NULL_POINTER;                                           \
   259   nsISupports* foundInterface;                                              \
   260   if ( aIID.Equals(NS_GET_IID(nsISupports)) )                               \
   261     foundInterface = InnerObject();                                         \
   262   else
   264 #define NS_IMPL_AGGREGATED_QUERY_CYCLE_COLLECTION(_class)                   \
   265   if (aIID.Equals(IsPartOfAggregated() ?                                    \
   266                   NS_GET_IID(nsCycleCollectionParticipant) :                \
   267                   NS_GET_IID(nsAggregatedCycleCollectionParticipant)))      \
   268     foundInterface = NS_CYCLE_COLLECTION_PARTICIPANT(_class);               \
   269   else
   271 #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_AGGREGATED(_class)          \
   272   NS_IMETHODIMP                                                             \
   273   NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse                           \
   274                          (void *p, nsCycleCollectionTraversalCallback &cb)  \
   275   {                                                                         \
   276     nsISupports *s = static_cast<nsISupports*>(p);                          \
   277     MOZ_ASSERT(CheckForRightISupports(s),                                   \
   278                "not the nsISupports pointer we expect");                    \
   279     _class *tmp = static_cast<_class*>(Downcast(s));                        \
   280     if (!tmp->IsPartOfAggregated())                                         \
   281         NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
   283 #define NS_GENERIC_AGGREGATED_CONSTRUCTOR(_InstanceClass)                   \
   284 static nsresult                                                             \
   285 _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID,             \
   286                             void **aResult)                                 \
   287 {                                                                           \
   288     *aResult = nullptr;                                                     \
   289     if (NS_WARN_IF(aOuter && !aIID.Equals(NS_GET_IID(nsISupports))))        \
   290         return NS_ERROR_INVALID_ARG;                                        \
   291                                                                             \
   292     _InstanceClass* inst = new _InstanceClass(aOuter);                      \
   293     if (!inst) {                                                            \
   294         return NS_ERROR_OUT_OF_MEMORY;                                      \
   295     }                                                                       \
   296                                                                             \
   297     nsISupports* inner = inst->InnerObject();                               \
   298     nsresult rv = inner->QueryInterface(aIID, aResult);                     \
   299     if (NS_FAILED(rv)) {                                                    \
   300         delete inst;                                                        \
   301     }                                                                       \
   302                                                                             \
   303     return rv;                                                              \
   304 }                                                                           \
   306 #define NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(_InstanceClass, _InitMethod) \
   307 static nsresult                                                             \
   308 _InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID,             \
   309                             void **aResult)                                 \
   310 {                                                                           \
   311     *aResult = nullptr;                                                     \
   312     if (NS_WARN_IF(aOuter && !aIID.Equals(NS_GET_IID(nsISupports))))        \
   313         return NS_ERROR_INVALID_ARG;                                        \
   314                                                                             \
   315     _InstanceClass* inst = new _InstanceClass(aOuter);                      \
   316     if (!inst) {                                                            \
   317         return NS_ERROR_OUT_OF_MEMORY;                                      \
   318     }                                                                       \
   319                                                                             \
   320     nsISupports* inner = inst->InnerObject();                               \
   321     NS_ADDREF(inner);                                                       \
   322     nsresult rv = inst->_InitMethod();                                      \
   323     if (NS_SUCCEEDED(rv)) {                                                 \
   324         rv = inner->QueryInterface(aIID, aResult);                          \
   325     }                                                                       \
   326     NS_RELEASE(inner);                                                      \
   327                                                                             \
   328     return rv;                                                              \
   329 }                                                                           \
   331 #endif /* nsAgg_h___ */

mercurial