intrusive_ref_counter.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Copyright Andrey Semashev 2007 - 2013.
  3. * Distributed under the Boost Software License, Version 1.0.
  4. * (See accompanying file LICENSE_1_0.txt or copy at
  5. * http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. /*!
  8. * \file intrusive_ref_counter.hpp
  9. * \author Andrey Semashev
  10. * \date 12.03.2009
  11. *
  12. * This header contains a reference counter class for \c intrusive_ptr.
  13. */
  14. #ifndef BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
  15. #define BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
  16. #include <boost/config.hpp>
  17. #include <boost/smart_ptr/detail/atomic_count.hpp>
  18. #include <boost/smart_ptr/detail/sp_noexcept.hpp>
  19. #ifdef BOOST_HAS_PRAGMA_ONCE
  20. #pragma once
  21. #endif
  22. #if defined(_MSC_VER)
  23. #pragma warning(push)
  24. // This is a bogus MSVC warning, which is flagged by friend declarations of intrusive_ptr_add_ref and intrusive_ptr_release in intrusive_ref_counter:
  25. // 'name' : the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
  26. // Note that there is no inline specifier in the declarations.
  27. #pragma warning(disable: 4396)
  28. #endif
  29. namespace boost {
  30. namespace sp_adl_block {
  31. /*!
  32. * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter
  33. *
  34. * The policy instructs the \c intrusive_ref_counter base class to implement
  35. * a reference counter suitable for single threaded use only. Pointers to the same
  36. * object with this kind of reference counter must not be used by different threads.
  37. */
  38. struct thread_unsafe_counter
  39. {
  40. typedef unsigned int type;
  41. static unsigned int load(unsigned int const& counter) BOOST_SP_NOEXCEPT
  42. {
  43. return counter;
  44. }
  45. static void increment(unsigned int& counter) BOOST_SP_NOEXCEPT
  46. {
  47. ++counter;
  48. }
  49. static unsigned int decrement(unsigned int& counter) BOOST_SP_NOEXCEPT
  50. {
  51. return --counter;
  52. }
  53. };
  54. /*!
  55. * \brief Thread safe reference counter policy for \c intrusive_ref_counter
  56. *
  57. * The policy instructs the \c intrusive_ref_counter base class to implement
  58. * a thread-safe reference counter, if the target platform supports multithreading.
  59. */
  60. struct thread_safe_counter
  61. {
  62. typedef boost::detail::atomic_count type;
  63. static unsigned int load(boost::detail::atomic_count const& counter) BOOST_SP_NOEXCEPT
  64. {
  65. return static_cast< unsigned int >(static_cast< long >(counter));
  66. }
  67. static void increment(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
  68. {
  69. ++counter;
  70. }
  71. static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
  72. {
  73. return static_cast< unsigned int >(--counter);
  74. }
  75. };
  76. template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
  77. class intrusive_ref_counter;
  78. template< typename DerivedT, typename CounterPolicyT >
  79. void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
  80. template< typename DerivedT, typename CounterPolicyT >
  81. void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
  82. /*!
  83. * \brief A reference counter base class
  84. *
  85. * This base class can be used with user-defined classes to add support
  86. * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT.
  87. * Upon releasing the last \c intrusive_ptr referencing the object
  88. * derived from the \c intrusive_ref_counter class, operator \c delete
  89. * is automatically called on the pointer to the object.
  90. *
  91. * The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter.
  92. */
  93. template< typename DerivedT, typename CounterPolicyT >
  94. class intrusive_ref_counter
  95. {
  96. private:
  97. //! Reference counter type
  98. typedef typename CounterPolicyT::type counter_type;
  99. //! Reference counter
  100. mutable counter_type m_ref_counter;
  101. public:
  102. /*!
  103. * Default constructor
  104. *
  105. * \post <tt>use_count() == 0</tt>
  106. */
  107. intrusive_ref_counter() BOOST_SP_NOEXCEPT : m_ref_counter(0)
  108. {
  109. }
  110. /*!
  111. * Copy constructor
  112. *
  113. * \post <tt>use_count() == 0</tt>
  114. */
  115. intrusive_ref_counter(intrusive_ref_counter const&) BOOST_SP_NOEXCEPT : m_ref_counter(0)
  116. {
  117. }
  118. /*!
  119. * Assignment
  120. *
  121. * \post The reference counter is not modified after assignment
  122. */
  123. intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_SP_NOEXCEPT { return *this; }
  124. /*!
  125. * \return The reference counter
  126. */
  127. unsigned int use_count() const BOOST_SP_NOEXCEPT
  128. {
  129. return CounterPolicyT::load(m_ref_counter);
  130. }
  131. protected:
  132. /*!
  133. * Destructor
  134. */
  135. BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {})
  136. friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
  137. friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
  138. };
  139. template< typename DerivedT, typename CounterPolicyT >
  140. inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
  141. {
  142. CounterPolicyT::increment(p->m_ref_counter);
  143. }
  144. template< typename DerivedT, typename CounterPolicyT >
  145. inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
  146. {
  147. if (CounterPolicyT::decrement(p->m_ref_counter) == 0)
  148. delete static_cast< const DerivedT* >(p);
  149. }
  150. } // namespace sp_adl_block
  151. using sp_adl_block::intrusive_ref_counter;
  152. using sp_adl_block::thread_unsafe_counter;
  153. using sp_adl_block::thread_safe_counter;
  154. } // namespace boost
  155. #if defined(_MSC_VER)
  156. #pragma warning(pop)
  157. #endif
  158. #endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_