llcorerefcounted.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**
  2. * @file llcorerefcounted.h
  3. * @brief Atomic, thread-safe ref counting and destruction mixin class
  4. *
  5. * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2012, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LLCOREINT__REFCOUNTED_H_
  27. #define LLCOREINT__REFCOUNTED_H_
  28. #include "llatomic.h"
  29. #include "boost/intrusive_ptr.hpp"
  30. namespace LLCoreInt
  31. {
  32. class RefCounted
  33. {
  34. private:
  35. RefCounted() = delete;
  36. void operator=(const RefCounted&) = delete;
  37. public:
  38. explicit RefCounted(bool implicit)
  39. : mRefCount(S32(implicit))
  40. {
  41. }
  42. // Ref-count interface
  43. LL_INLINE void addRef() const
  44. {
  45. S32 count = ++mRefCount;
  46. llassert_always(count >= 0);
  47. }
  48. LL_INLINE void release() const
  49. {
  50. S32 count = mRefCount;
  51. llassert_always(count != NOT_REF_COUNTED && count > 0);
  52. count = --mRefCount;
  53. // Clean ourselves up if that was the last reference
  54. if (count == 0)
  55. {
  56. const_cast<RefCounted*>(this)->destroySelf();
  57. }
  58. }
  59. LL_INLINE bool isLastRef() const
  60. {
  61. const S32 count = mRefCount;
  62. llassert_always(count != NOT_REF_COUNTED && count >= 1);
  63. return count == 1;
  64. }
  65. LL_INLINE S32 getRefCount() const
  66. {
  67. const S32 result = mRefCount;
  68. return result;
  69. }
  70. LL_INLINE void noRef() const
  71. {
  72. llassert_always(mRefCount <= 1);
  73. mRefCount = NOT_REF_COUNTED;
  74. }
  75. static constexpr S32 NOT_REF_COUNTED = -1;
  76. protected:
  77. virtual ~RefCounted() = default;
  78. LL_INLINE virtual void destroySelf()
  79. {
  80. delete this;
  81. }
  82. private:
  83. mutable LLAtomicS32 mRefCount;
  84. }; // End class RefCounted
  85. // boost::intrusive_ptr may be used to manage RefCounted classes. Unfortunately
  86. // RefCounted and boost::intrusive_ptr use different conventions for the
  87. // initial refcount value. To avoid leaky (immortal) objects, you should really
  88. // construct boost::intrusive_ptr<RefCounted*>(rawptr, false). IntrusivePtr<T>
  89. // encapsulates that for you.
  90. template <typename T>
  91. struct IntrusivePtr : public boost::intrusive_ptr<T>
  92. {
  93. IntrusivePtr()
  94. : boost::intrusive_ptr<T>()
  95. {
  96. }
  97. IntrusivePtr(T* p)
  98. : boost::intrusive_ptr<T>(p, false)
  99. {
  100. }
  101. };
  102. LL_INLINE void intrusive_ptr_add_ref(RefCounted* p)
  103. {
  104. p->addRef();
  105. }
  106. LL_INLINE void intrusive_ptr_release(RefCounted* p)
  107. {
  108. p->release();
  109. }
  110. } // End namespace LLCoreInt
  111. #endif // LLCOREINT__REFCOUNTED_H_