nsISupportsUtils.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef nsISupportsUtils_h__
  6. #define nsISupportsUtils_h__
  7. #include "nscore.h"
  8. #include "nsISupportsBase.h"
  9. #include "nsError.h"
  10. #include "nsDebug.h"
  11. #include "nsISupportsImpl.h"
  12. #include "mozilla/RefPtr.h"
  13. #include "mozilla/TypeTraits.h"
  14. /**
  15. * Macro for adding a reference to an interface.
  16. * @param _ptr The interface pointer.
  17. */
  18. #define NS_ADDREF(_ptr) \
  19. (_ptr)->AddRef()
  20. /**
  21. * Macro for adding a reference to this. This macro should be used
  22. * because NS_ADDREF (when tracing) may require an ambiguous cast
  23. * from the pointers primary type to nsISupports. This macro sidesteps
  24. * that entire problem.
  25. */
  26. #define NS_ADDREF_THIS() \
  27. AddRef()
  28. // Making this a |inline| |template| allows |aExpr| to be evaluated only once,
  29. // yet still denies you the ability to |AddRef()| an |nsCOMPtr|.
  30. template<class T>
  31. inline void
  32. ns_if_addref(T aExpr)
  33. {
  34. if (aExpr) {
  35. aExpr->AddRef();
  36. }
  37. }
  38. /**
  39. * Macro for adding a reference to an interface that checks for nullptr.
  40. * @param _expr The interface pointer.
  41. */
  42. #define NS_IF_ADDREF(_expr) ns_if_addref(_expr)
  43. /*
  44. * Given these declarations, it explicitly OK and efficient to end a `getter' with:
  45. *
  46. * NS_IF_ADDREF(*result = mThing);
  47. *
  48. * even if |mThing| is an |nsCOMPtr|. If |mThing| is an |nsCOMPtr|, however, it is still
  49. * _illegal_ to say |NS_IF_ADDREF(mThing)|.
  50. */
  51. /**
  52. * Macro for releasing a reference to an interface.
  53. * @param _ptr The interface pointer.
  54. */
  55. #define NS_RELEASE(_ptr) \
  56. do { \
  57. (_ptr)->Release(); \
  58. (_ptr) = 0; \
  59. } while (0)
  60. /**
  61. * Macro for releasing a reference to this interface.
  62. */
  63. #define NS_RELEASE_THIS() \
  64. Release()
  65. /**
  66. * Macro for releasing a reference to an interface, except that this
  67. * macro preserves the return value from the underlying Release call.
  68. * The interface pointer argument will only be NULLed if the reference count
  69. * goes to zero.
  70. *
  71. * @param _ptr The interface pointer.
  72. * @param _rc The reference count.
  73. */
  74. #define NS_RELEASE2(_ptr, _rc) \
  75. do { \
  76. _rc = (_ptr)->Release(); \
  77. if (0 == (_rc)) (_ptr) = 0; \
  78. } while (0)
  79. /**
  80. * Macro for releasing a reference to an interface that checks for nullptr;
  81. * @param _ptr The interface pointer.
  82. */
  83. #define NS_IF_RELEASE(_ptr) \
  84. do { \
  85. if (_ptr) { \
  86. (_ptr)->Release(); \
  87. (_ptr) = 0; \
  88. } \
  89. } while (0)
  90. /*
  91. * Often you have to cast an implementation pointer, e.g., |this|, to an
  92. * |nsISupports*|, but because you have multiple inheritance, a simple cast
  93. * is ambiguous. One could simply say, e.g., (given a base |nsIBase|),
  94. * |static_cast<nsIBase*>(this)|; but that disguises the fact that what
  95. * you are really doing is disambiguating the |nsISupports|. You could make
  96. * that more obvious with a double cast, e.g., |static_cast<nsISupports*>
  97. (* static_cast<nsIBase*>(this))|, but that is bulky and harder to read...
  98. *
  99. * The following macro is clean, short, and obvious. In the example above,
  100. * you would use it like this: |NS_ISUPPORTS_CAST(nsIBase*, this)|.
  101. */
  102. #define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \
  103. static_cast<nsISupports*>(static_cast<__unambiguousBase>(__expr))
  104. // a type-safe shortcut for calling the |QueryInterface()| member function
  105. template<class T, class DestinationType>
  106. inline nsresult
  107. CallQueryInterface(T* aSource, DestinationType** aDestination)
  108. {
  109. // We permit nsISupports-to-nsISupports here so that one can still obtain
  110. // the canonical nsISupports pointer with CallQueryInterface.
  111. static_assert(!mozilla::IsSame<T, DestinationType>::value ||
  112. mozilla::IsSame<DestinationType, nsISupports>::value,
  113. "don't use CallQueryInterface for compile-time-determinable casts");
  114. NS_PRECONDITION(aSource, "null parameter");
  115. NS_PRECONDITION(aDestination, "null parameter");
  116. return aSource->QueryInterface(NS_GET_TEMPLATE_IID(DestinationType),
  117. reinterpret_cast<void**>(aDestination));
  118. }
  119. template <class SourceType, class DestinationType>
  120. inline nsresult
  121. CallQueryInterface(RefPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr)
  122. {
  123. return CallQueryInterface(aSourcePtr.get(), aDestPtr);
  124. }
  125. #endif /* __nsISupportsUtils_h */