Handle.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Badge.h>
  8. #include <AK/IntrusiveList.h>
  9. #include <AK/Noncopyable.h>
  10. #include <AK/RefCounted.h>
  11. #include <AK/RefPtr.h>
  12. #include <LibJS/Forward.h>
  13. #include <LibJS/Runtime/Value.h>
  14. namespace JS {
  15. class HandleImpl : public RefCounted<HandleImpl> {
  16. AK_MAKE_NONCOPYABLE(HandleImpl);
  17. AK_MAKE_NONMOVABLE(HandleImpl);
  18. public:
  19. ~HandleImpl();
  20. Cell* cell() { return m_cell; }
  21. const Cell* cell() const { return m_cell; }
  22. private:
  23. template<class T>
  24. friend class Handle;
  25. explicit HandleImpl(Cell*);
  26. Cell* m_cell { nullptr };
  27. IntrusiveListNode<HandleImpl> m_list_node;
  28. public:
  29. using List = IntrusiveList<&HandleImpl::m_list_node>;
  30. };
  31. template<class T>
  32. class Handle {
  33. public:
  34. Handle() = default;
  35. static Handle create(T* cell)
  36. {
  37. return Handle(adopt_ref(*new HandleImpl(cell)));
  38. }
  39. T* cell() { return static_cast<T*>(m_impl->cell()); }
  40. const T* cell() const { return static_cast<const T*>(m_impl->cell()); }
  41. bool is_null() const { return m_impl.is_null(); }
  42. T* operator->() { return cell(); }
  43. T const* operator->() const { return cell(); }
  44. private:
  45. explicit Handle(NonnullRefPtr<HandleImpl> impl)
  46. : m_impl(move(impl))
  47. {
  48. }
  49. RefPtr<HandleImpl> m_impl;
  50. };
  51. template<class T>
  52. inline Handle<T> make_handle(T* cell)
  53. {
  54. return Handle<T>::create(cell);
  55. }
  56. template<class T>
  57. inline Handle<T> make_handle(T& cell)
  58. {
  59. return Handle<T>::create(&cell);
  60. }
  61. template<>
  62. class Handle<Value> {
  63. public:
  64. Handle() = default;
  65. static Handle create(Value value)
  66. {
  67. if (value.is_cell())
  68. return Handle(value, &value.as_cell());
  69. return Handle(value);
  70. }
  71. auto cell() { return m_handle.cell(); }
  72. auto cell() const { return m_handle.cell(); }
  73. auto value() const { return m_value; }
  74. bool is_null() const { return m_handle.is_null(); }
  75. private:
  76. explicit Handle(Value value)
  77. : m_value(value)
  78. {
  79. }
  80. explicit Handle(Value value, Cell* cell)
  81. : m_value(value)
  82. , m_handle(Handle<Cell>::create(cell))
  83. {
  84. }
  85. Value m_value;
  86. Handle<Cell> m_handle;
  87. };
  88. inline Handle<Value> make_handle(Value value)
  89. {
  90. return Handle<Value>::create(value);
  91. }
  92. }