xpcom/glue/nsISupportsUtils.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 nsISupportsUtils_h__
     7 #define nsISupportsUtils_h__
     9 #include "nscore.h"
    10 #include "nsISupportsBase.h"
    11 #include "nsError.h"
    12 #include "nsDebug.h"
    13 #include "nsISupportsImpl.h"
    14 #include "mozilla/TypeTraits.h"
    16 /**
    17  * Macro for adding a reference to an interface.
    18  * @param _ptr The interface pointer.
    19  */
    20 #define NS_ADDREF(_ptr) \
    21   (_ptr)->AddRef()
    23 /**
    24  * Macro for adding a reference to this. This macro should be used
    25  * because NS_ADDREF (when tracing) may require an ambiguous cast
    26  * from the pointers primary type to nsISupports. This macro sidesteps
    27  * that entire problem.
    28  */
    29 #define NS_ADDREF_THIS() \
    30   AddRef()
    33 extern "C++" {
    34 // ...because some one is accidentally including this file inside
    35 // an |extern "C"|
    38 // Making this a |inline| |template| allows |expr| to be evaluated only once,
    39 // yet still denies you the ability to |AddRef()| an |nsCOMPtr|.
    40 template <class T>
    41 inline
    42 void
    43 ns_if_addref( T expr )
    44 {
    45     if (expr) {
    46         expr->AddRef();
    47     }
    48 }
    50 } /* extern "C++" */
    52 /**
    53  * Macro for adding a reference to an interface that checks for nullptr.
    54  * @param _expr The interface pointer.
    55  */
    56 #define NS_IF_ADDREF(_expr) ns_if_addref(_expr)
    58 /*
    59  * Given these declarations, it explicitly OK and efficient to end a `getter' with:
    60  *
    61  *    NS_IF_ADDREF(*result = mThing);
    62  *
    63  * even if |mThing| is an |nsCOMPtr|.  If |mThing| is an |nsCOMPtr|, however, it is still
    64  * _illegal_ to say |NS_IF_ADDREF(mThing)|.
    65  */
    67 /**
    68  * Macro for releasing a reference to an interface.
    69  * @param _ptr The interface pointer.
    70  */
    71 #define NS_RELEASE(_ptr)                                                      \
    72   do {                                                                        \
    73     (_ptr)->Release();                                                        \
    74     (_ptr) = 0;                                                               \
    75   } while (0)
    77 /**
    78  * Macro for releasing a reference to this interface.
    79  */
    80 #define NS_RELEASE_THIS() \
    81     Release()
    83 /**
    84  * Macro for releasing a reference to an interface, except that this
    85  * macro preserves the return value from the underlying Release call.
    86  * The interface pointer argument will only be NULLed if the reference count
    87  * goes to zero.
    88  *
    89  * @param _ptr The interface pointer.
    90  * @param _rc  The reference count.
    91  */
    92 #define NS_RELEASE2(_ptr, _rc)                                                \
    93   do {                                                                        \
    94     _rc = (_ptr)->Release();                                                  \
    95     if (0 == (_rc)) (_ptr) = 0;                                               \
    96   } while (0)
    98 /**
    99  * Macro for releasing a reference to an interface that checks for nullptr;
   100  * @param _ptr The interface pointer.
   101  */
   102 #define NS_IF_RELEASE(_ptr)                                                   \
   103   do {                                                                        \
   104     if (_ptr) {                                                               \
   105       (_ptr)->Release();                                                      \
   106       (_ptr) = 0;                                                             \
   107     }                                                                         \
   108   } while (0)
   110 /*
   111  * Often you have to cast an implementation pointer, e.g., |this|, to an
   112  * |nsISupports*|, but because you have multiple inheritance, a simple cast
   113  * is ambiguous.  One could simply say, e.g., (given a base |nsIBase|),
   114  * |static_cast<nsIBase*>(this)|; but that disguises the fact that what
   115  * you are really doing is disambiguating the |nsISupports|.  You could make
   116  * that more obvious with a double cast, e.g., |static_cast<nsISupports*>
   117                                                            (* static_cast<nsIBase*>(this))|, but that is bulky and harder to read...
   118  *
   119  * The following macro is clean, short, and obvious.  In the example above,
   120  * you would use it like this: |NS_ISUPPORTS_CAST(nsIBase*, this)|.
   121  */
   123 #define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \
   124   static_cast<nsISupports*>(static_cast<__unambiguousBase>(__expr))
   126 // a type-safe shortcut for calling the |QueryInterface()| member function
   127 template <class T, class DestinationType>
   128 inline
   129 nsresult
   130 CallQueryInterface( T* aSource, DestinationType** aDestination )
   131 {
   132     // We permit nsISupports-to-nsISupports here so that one can still obtain
   133     // the canonical nsISupports pointer with CallQueryInterface.
   134     static_assert(!mozilla::IsSame<T, DestinationType>::value ||
   135                   mozilla::IsSame<DestinationType, nsISupports>::value,
   136                   "don't use CallQueryInterface for compile-time-determinable casts");
   138     NS_PRECONDITION(aSource, "null parameter");
   139     NS_PRECONDITION(aDestination, "null parameter");
   141     return aSource->QueryInterface(NS_GET_TEMPLATE_IID(DestinationType),
   142                                    reinterpret_cast<void**>(aDestination));
   143 }
   145 #endif /* __nsISupportsUtils_h */

mercurial