GCPtr.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Traits.h>
  8. #include <AK/Types.h>
  9. namespace JS {
  10. template<typename T>
  11. class GCPtr;
  12. template<typename T>
  13. class NonnullGCPtr {
  14. public:
  15. NonnullGCPtr() = delete;
  16. NonnullGCPtr(T& ptr)
  17. : m_ptr(&ptr)
  18. {
  19. }
  20. template<typename U>
  21. NonnullGCPtr(U& ptr)
  22. requires(IsConvertible<U*, T*>)
  23. : m_ptr(&static_cast<T&>(ptr))
  24. {
  25. }
  26. NonnullGCPtr(NonnullGCPtr const& other)
  27. : m_ptr(other.ptr())
  28. {
  29. }
  30. template<typename U>
  31. NonnullGCPtr(NonnullGCPtr<U> const& other)
  32. requires(IsConvertible<U*, T*>)
  33. : m_ptr(other.ptr())
  34. {
  35. }
  36. NonnullGCPtr& operator=(NonnullGCPtr const& other)
  37. {
  38. m_ptr = other.ptr();
  39. return *this;
  40. }
  41. template<typename U>
  42. NonnullGCPtr& operator=(NonnullGCPtr<U> const& other)
  43. requires(IsConvertible<U*, T*>)
  44. {
  45. m_ptr = static_cast<T*>(other.ptr());
  46. return *this;
  47. }
  48. NonnullGCPtr& operator=(T& other)
  49. {
  50. m_ptr = &other;
  51. return *this;
  52. }
  53. template<typename U>
  54. NonnullGCPtr& operator=(U& other)
  55. requires(IsConvertible<U*, T*>)
  56. {
  57. m_ptr = &static_cast<T&>(other);
  58. return *this;
  59. }
  60. T* operator->() const { return m_ptr; }
  61. T& operator*() const { return *m_ptr; }
  62. T* ptr() const { return m_ptr; }
  63. operator T*() const { return m_ptr; }
  64. operator T&() const { return *m_ptr; }
  65. private:
  66. T* m_ptr { nullptr };
  67. };
  68. template<typename T>
  69. class GCPtr {
  70. public:
  71. GCPtr() = default;
  72. GCPtr(T& ptr)
  73. : m_ptr(&ptr)
  74. {
  75. }
  76. GCPtr(T* ptr)
  77. : m_ptr(ptr)
  78. {
  79. }
  80. GCPtr(GCPtr<T> const& other)
  81. : m_ptr(other.ptr())
  82. {
  83. }
  84. template<typename U>
  85. GCPtr(GCPtr<U> const& other)
  86. requires(IsConvertible<U*, T*>)
  87. : m_ptr(other.ptr())
  88. {
  89. }
  90. GCPtr(NonnullGCPtr<T> const& other)
  91. : m_ptr(other.ptr())
  92. {
  93. }
  94. template<typename U>
  95. GCPtr(NonnullGCPtr<U> const& other)
  96. requires(IsConvertible<U*, T*>)
  97. : m_ptr(other.ptr())
  98. {
  99. }
  100. GCPtr(nullptr_t)
  101. : m_ptr(nullptr)
  102. {
  103. }
  104. GCPtr& operator=(GCPtr const&) = default;
  105. template<typename U>
  106. GCPtr& operator=(GCPtr<U> const& other)
  107. requires(IsConvertible<U*, T*>)
  108. {
  109. m_ptr = static_cast<T*>(other.ptr());
  110. return *this;
  111. }
  112. GCPtr& operator=(NonnullGCPtr<T> const& other)
  113. {
  114. m_ptr = other.ptr();
  115. return *this;
  116. }
  117. template<typename U>
  118. GCPtr& operator=(NonnullGCPtr<U> const& other)
  119. requires(IsConvertible<U*, T*>)
  120. {
  121. m_ptr = static_cast<T*>(other.ptr());
  122. return *this;
  123. }
  124. GCPtr& operator=(T& other)
  125. {
  126. m_ptr = &other;
  127. return *this;
  128. }
  129. template<typename U>
  130. GCPtr& operator=(U& other)
  131. requires(IsConvertible<U*, T*>)
  132. {
  133. m_ptr = &static_cast<T&>(other);
  134. return *this;
  135. }
  136. GCPtr& operator=(T* other)
  137. {
  138. m_ptr = other;
  139. return *this;
  140. }
  141. template<typename U>
  142. GCPtr& operator=(U* other)
  143. requires(IsConvertible<U*, T*>)
  144. {
  145. m_ptr = static_cast<T*>(other);
  146. return *this;
  147. }
  148. T* operator->() const
  149. {
  150. VERIFY(m_ptr);
  151. return m_ptr;
  152. }
  153. T& operator*() const
  154. {
  155. VERIFY(m_ptr);
  156. return *m_ptr;
  157. }
  158. T* ptr() const { return m_ptr; }
  159. operator bool() const { return !!m_ptr; }
  160. bool operator!() const { return !m_ptr; }
  161. operator T*() const { return m_ptr; }
  162. private:
  163. T* m_ptr { nullptr };
  164. };
  165. template<typename T, typename U>
  166. inline bool operator==(GCPtr<T> const& a, GCPtr<U> const& b)
  167. {
  168. return a.ptr() == b.ptr();
  169. }
  170. template<typename T, typename U>
  171. inline bool operator==(GCPtr<T> const& a, NonnullGCPtr<U> const& b)
  172. {
  173. return a.ptr() == b.ptr();
  174. }
  175. template<typename T, typename U>
  176. inline bool operator==(NonnullGCPtr<T> const& a, NonnullGCPtr<U> const& b)
  177. {
  178. return a.ptr() == b.ptr();
  179. }
  180. template<typename T, typename U>
  181. inline bool operator==(NonnullGCPtr<T> const& a, GCPtr<U> const& b)
  182. {
  183. return a.ptr() == b.ptr();
  184. }
  185. }
  186. namespace AK {
  187. template<typename T>
  188. struct Traits<JS::GCPtr<T>> : public GenericTraits<JS::GCPtr<T>> {
  189. static unsigned hash(JS::GCPtr<T> const& value)
  190. {
  191. return Traits<T*>::hash(value.ptr());
  192. }
  193. };
  194. template<typename T>
  195. struct Traits<JS::NonnullGCPtr<T>> : public GenericTraits<JS::NonnullGCPtr<T>> {
  196. static unsigned hash(JS::NonnullGCPtr<T> const& value)
  197. {
  198. return Traits<T*>::hash(value.ptr());
  199. }
  200. };
  201. }