HandleRefPtr.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* -*- Mode: C++; tab-width: 2; 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. */
  6. /* smart pointer for strong references to objects through pointer-like
  7. * "handle" objects */
  8. #include <algorithm>
  9. #include "mozilla/Assertions.h"
  10. #ifndef mozilla_HandleRefPtr_h
  11. #define mozilla_HandleRefPtr_h
  12. namespace mozilla {
  13. /**
  14. * A class for holding strong references to handle-managed objects.
  15. *
  16. * This is intended for use with objects like RestyleManagerHandle,
  17. * where the handle type is not a pointer but which can still have
  18. * ->AddRef() and ->Release() called on it.
  19. */
  20. template<typename T>
  21. class HandleRefPtr
  22. {
  23. public:
  24. HandleRefPtr() {}
  25. HandleRefPtr(HandleRefPtr<T>& aRhs)
  26. {
  27. assign(aRhs.mHandle);
  28. }
  29. HandleRefPtr(HandleRefPtr<T>&& aRhs)
  30. {
  31. std::swap(mHandle, aRhs.mHandle);
  32. }
  33. MOZ_IMPLICIT HandleRefPtr(T aRhs)
  34. {
  35. assign(aRhs);
  36. }
  37. HandleRefPtr<T>& operator=(HandleRefPtr<T>& aRhs)
  38. {
  39. assign(aRhs.mHandle);
  40. return *this;
  41. }
  42. HandleRefPtr<T>& operator=(T aRhs)
  43. {
  44. assign(aRhs);
  45. return *this;
  46. }
  47. ~HandleRefPtr() { assign(nullptr); }
  48. explicit operator bool() const { return !!mHandle; }
  49. bool operator!() const { return !mHandle; }
  50. operator T() const { return mHandle; }
  51. T operator->() const { return mHandle; }
  52. void swap(HandleRefPtr<T>& aOther)
  53. {
  54. std::swap(mHandle, aOther.mHandle);
  55. }
  56. private:
  57. void assign(T aPtr)
  58. {
  59. // AddRef early so |aPtr| can't disappear underneath us.
  60. if (aPtr) {
  61. aPtr->AddRef();
  62. }
  63. // Don't release |mHandle| yet: if |mHandle| indirectly owns |this|,
  64. // releasing would invalidate |this|. Swap |aPtr| for |mHandle| so that
  65. // |aPtr| lives as long as |this|, then release the new |aPtr| (really the
  66. // original |mHandle|) so that if |this| is invalidated, we're not using it
  67. // any more.
  68. std::swap(mHandle, aPtr);
  69. if (aPtr) {
  70. aPtr->Release();
  71. }
  72. }
  73. T mHandle;
  74. };
  75. template<typename T>
  76. inline bool operator==(const HandleRefPtr<T>& aLHS, const HandleRefPtr<T>& aRHS)
  77. {
  78. return static_cast<T>(aLHS) == static_cast<T>(aRHS);
  79. }
  80. template<typename T>
  81. inline bool operator==(const HandleRefPtr<T>& aLHS, T aRHS)
  82. {
  83. return static_cast<T>(aLHS) == aRHS;
  84. }
  85. template<typename T>
  86. inline bool operator==(T aLHS, const HandleRefPtr<T>& aRHS)
  87. {
  88. return aLHS == static_cast<T>(aRHS);
  89. }
  90. template<typename T>
  91. inline bool operator!=(const HandleRefPtr<T>& aLHS, const HandleRefPtr<T>& aRHS)
  92. {
  93. return !(aLHS == aRHS);
  94. }
  95. template<typename T>
  96. inline bool operator!=(const HandleRefPtr<T>& aLHS, T aRHS)
  97. {
  98. return !(aLHS == aRHS);
  99. }
  100. template<typename T>
  101. inline bool operator!=(T aLHS, const HandleRefPtr<T>& aRHS)
  102. {
  103. return !(aLHS == aRHS);
  104. }
  105. } // namespace mozilla
  106. #endif // mozilla_HandleRefPtr_h