ref_counted.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #pragma once
  2. #include <library/cpp/yt/misc/port.h>
  3. #include <library/cpp/yt/assert/assert.h>
  4. #include <atomic>
  5. namespace NYT {
  6. ////////////////////////////////////////////////////////////////////////////////
  7. //! A technical base class for ref-counted objects and promise states.
  8. class TRefCountedBase
  9. {
  10. public:
  11. TRefCountedBase() = default;
  12. TRefCountedBase(const TRefCountedBase&) = delete;
  13. TRefCountedBase(TRefCountedBase&&) = delete;
  14. TRefCountedBase& operator=(const TRefCountedBase&) = delete;
  15. TRefCountedBase& operator=(TRefCountedBase&&) = delete;
  16. virtual ~TRefCountedBase() noexcept = default;
  17. virtual void DestroyRefCounted() = 0;
  18. };
  19. ////////////////////////////////////////////////////////////////////////////////
  20. class TRefCounter
  21. {
  22. public:
  23. //! Returns current number of strong references to the object.
  24. /*!
  25. * Note that you should never ever use this method in production code.
  26. * This method is mainly for debugging purposes.
  27. */
  28. int GetRefCount() const noexcept;
  29. //! Increments the strong reference counter.
  30. void Ref(int n = 1) const noexcept;
  31. //! Increments the strong reference counter if it is not null.
  32. bool TryRef() const noexcept;
  33. //! Decrements the strong reference counter.
  34. bool Unref(int n = 1) const;
  35. //! Returns current number of weak references to the object.
  36. int GetWeakRefCount() const noexcept;
  37. //! Increments the weak reference counter.
  38. void WeakRef() const noexcept;
  39. //! Decrements the weak reference counter.
  40. bool WeakUnref() const;
  41. private:
  42. mutable std::atomic<int> StrongCount_ = 1;
  43. mutable std::atomic<int> WeakCount_ = 1;
  44. };
  45. ////////////////////////////////////////////////////////////////////////////////
  46. template <class T>
  47. const TRefCounter* GetRefCounter(const T* obj);
  48. template <class T>
  49. void DestroyRefCounted(const T* obj);
  50. template <class T>
  51. void DeallocateRefCounted(const T* obj);
  52. ////////////////////////////////////////////////////////////////////////////////
  53. template <class T>
  54. void Ref(T* obj, int n = 1);
  55. template <class T>
  56. void Unref(T* obj, int n = 1);
  57. ////////////////////////////////////////////////////////////////////////////////
  58. class TRefCounted
  59. : public TRefCountedBase
  60. , public TRefCounter
  61. {
  62. public:
  63. void Unref() const;
  64. void WeakUnref() const;
  65. protected:
  66. template <class T>
  67. static void DestroyRefCountedImpl(T* obj);
  68. };
  69. ////////////////////////////////////////////////////////////////////////////////
  70. // Forward declaration.
  71. template <class T>
  72. class TIntrusivePtr;
  73. using TRefCountedPtr = TIntrusivePtr<TRefCounted>;
  74. // A bunch of helpful macros that enable working with intrusive pointers to incomplete types.
  75. /*
  76. * Typically when you have a forward-declared type |T| and an instance
  77. * of |TIntrusivePtr<T>| you need the complete definition of |T| to work with
  78. * the pointer even if you're not actually using the members of |T|.
  79. * E.g. the dtor of |TIntrusivePtr<T>|, should you ever need it, must be able
  80. * to unref an instance of |T| and eventually destroy it.
  81. * This may force #inclusion of way more headers than really seems necessary.
  82. *
  83. * |DECLARE_REFCOUNTED_STRUCT|, |DECLARE_REFCOUNTED_CLASS|, and |DEFINE_REFCOUNTED_TYPE|
  84. * alleviate this issue by forcing TIntrusivePtr to work with the free-standing overloads
  85. * of |Ref| and |Unref| instead of their template version.
  86. * These overloads are declared together with the forward declaration of |T| and
  87. * are subsequently defined afterwards.
  88. */
  89. #define DECLARE_REFCOUNTED_TYPE(type) \
  90. using type ## Ptr = ::NYT::TIntrusivePtr<type>; \
  91. \
  92. [[maybe_unused]] YT_ATTRIBUTE_USED const ::NYT::TRefCounter* GetRefCounter(const type* obj); \
  93. [[maybe_unused]] YT_ATTRIBUTE_USED void DestroyRefCounted(const type* obj); \
  94. [[maybe_unused]] YT_ATTRIBUTE_USED void DeallocateRefCounted(const type* obj);
  95. //! Forward-declares a class type, defines an intrusive pointer for it, and finally
  96. //! declares Ref/Unref overloads. Use this macro in |public.h|-like files.
  97. #define DECLARE_REFCOUNTED_CLASS(type) \
  98. class type; \
  99. DECLARE_REFCOUNTED_TYPE(type)
  100. //! Forward-declares a struct type, defines an intrusive pointer for it, and finally
  101. //! declares Ref/Unref overloads. Use this macro in |public.h|-like files.
  102. #define DECLARE_REFCOUNTED_STRUCT(type) \
  103. struct type; \
  104. DECLARE_REFCOUNTED_TYPE(type)
  105. //! Provides implementations for Ref/Unref overloads. Use this macro right
  106. //! after the type's full definition.
  107. #define DEFINE_REFCOUNTED_TYPE(type) \
  108. [[maybe_unused]] YT_ATTRIBUTE_USED Y_FORCE_INLINE const ::NYT::TRefCounter* GetRefCounter(const type* obj) \
  109. { \
  110. return ::NYT::NDetail::TRefCountedTraits<type>::GetRefCounter(obj); \
  111. } \
  112. [[maybe_unused]] YT_ATTRIBUTE_USED Y_FORCE_INLINE void DestroyRefCounted(const type* obj) \
  113. { \
  114. ::NYT::NDetail::TRefCountedTraits<type>::Destroy(obj); \
  115. } \
  116. [[maybe_unused]] YT_ATTRIBUTE_USED Y_FORCE_INLINE void DeallocateRefCounted(const type* obj) \
  117. { \
  118. ::NYT::NDetail::TRefCountedTraits<type>::Deallocate(obj); \
  119. }
  120. //! Provides weak implementations for Ref/Unref overloads.
  121. //! Do not use if unsure.
  122. #define DEFINE_WEAK_REFCOUNTED_TYPE(type) \
  123. [[maybe_unused]] Y_WEAK YT_ATTRIBUTE_USED const ::NYT::TRefCounter* GetRefCounter(const type*) \
  124. { \
  125. YT_ABORT(); \
  126. } \
  127. [[maybe_unused]] Y_WEAK YT_ATTRIBUTE_USED void DestroyRefCounted(const type*) \
  128. { \
  129. YT_ABORT(); \
  130. } \
  131. [[maybe_unused]] Y_WEAK YT_ATTRIBUTE_USED void DeallocateRefCounted(const type*) \
  132. { \
  133. YT_ABORT(); \
  134. }
  135. ////////////////////////////////////////////////////////////////////////////////
  136. } // namespace NYT
  137. #define REF_COUNTED_INL_H_
  138. #include "ref_counted-inl.h"
  139. #undef REF_COUNTED_INL_H_