locking_ptr.hpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright Andrey Semashev 2007 - 2015.
  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 locking_ptr.hpp
  9. * \author Andrey Semashev
  10. * \date 15.07.2009
  11. *
  12. * This header is the Boost.Log library implementation, see the library documentation
  13. * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
  14. */
  15. #ifndef BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
  16. #define BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
  17. #include <cstddef>
  18. #include <boost/move/core.hpp>
  19. #include <boost/smart_ptr/shared_ptr.hpp>
  20. #include <boost/thread/lock_options.hpp>
  21. #include <boost/core/explicit_operator_bool.hpp>
  22. #include <boost/log/detail/config.hpp>
  23. #include <boost/log/detail/header.hpp>
  24. #ifdef BOOST_HAS_PRAGMA_ONCE
  25. #pragma once
  26. #endif
  27. namespace boost {
  28. BOOST_LOG_OPEN_NAMESPACE
  29. namespace aux {
  30. //! A pointer type that locks the backend until it's destroyed
  31. template< typename T, typename LockableT >
  32. class locking_ptr
  33. {
  34. typedef locking_ptr this_type;
  35. BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
  36. public:
  37. //! Pointed type
  38. typedef T element_type;
  39. private:
  40. //! Lockable type
  41. typedef LockableT lockable_type;
  42. private:
  43. //! The pointer to the backend
  44. shared_ptr< element_type > m_pElement;
  45. //! Reference to the shared lock control object
  46. lockable_type* m_pLock;
  47. public:
  48. //! Default constructor
  49. locking_ptr() BOOST_NOEXCEPT : m_pLock(NULL)
  50. {
  51. }
  52. //! Constructor
  53. locking_ptr(shared_ptr< element_type > const& p, lockable_type& l) : m_pElement(p), m_pLock(&l)
  54. {
  55. m_pLock->lock();
  56. }
  57. //! Constructor
  58. locking_ptr(shared_ptr< element_type > const& p, lockable_type& l, try_to_lock_t const&) : m_pElement(p), m_pLock(&l)
  59. {
  60. if (!m_pLock->try_lock())
  61. {
  62. m_pElement.reset();
  63. m_pLock = NULL;
  64. }
  65. }
  66. //! Copy constructor
  67. locking_ptr(locking_ptr const& that) : m_pElement(that.m_pElement), m_pLock(that.m_pLock)
  68. {
  69. if (m_pLock)
  70. m_pLock->lock();
  71. }
  72. //! Move constructor
  73. locking_ptr(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT : m_pLock(that.m_pLock)
  74. {
  75. m_pElement.swap(that.m_pElement);
  76. that.m_pLock = NULL;
  77. }
  78. //! Destructor
  79. ~locking_ptr()
  80. {
  81. if (m_pLock)
  82. m_pLock->unlock();
  83. }
  84. //! Assignment
  85. locking_ptr& operator= (locking_ptr that) BOOST_NOEXCEPT
  86. {
  87. this->swap(that);
  88. return *this;
  89. }
  90. //! Indirection
  91. element_type* operator-> () const BOOST_NOEXCEPT { return m_pElement.get(); }
  92. //! Dereferencing
  93. element_type& operator* () const BOOST_NOEXCEPT { return *m_pElement; }
  94. //! Accessor to the raw pointer
  95. element_type* get() const BOOST_NOEXCEPT { return m_pElement.get(); }
  96. //! Checks for null pointer
  97. BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
  98. //! Checks for null pointer
  99. bool operator! () const BOOST_NOEXCEPT { return !m_pElement; }
  100. //! Swaps two pointers
  101. void swap(locking_ptr& that) BOOST_NOEXCEPT
  102. {
  103. m_pElement.swap(that.m_pElement);
  104. lockable_type* p = m_pLock;
  105. m_pLock = that.m_pLock;
  106. that.m_pLock = p;
  107. }
  108. };
  109. //! Free raw pointer getter to assist generic programming
  110. template< typename T, typename LockableT >
  111. inline T* get_pointer(locking_ptr< T, LockableT > const& p) BOOST_NOEXCEPT
  112. {
  113. return p.get();
  114. }
  115. //! Free swap operation
  116. template< typename T, typename LockableT >
  117. inline void swap(locking_ptr< T, LockableT >& left, locking_ptr< T, LockableT >& right) BOOST_NOEXCEPT
  118. {
  119. left.swap(right);
  120. }
  121. } // namespace aux
  122. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  123. } // namespace boost
  124. #include <boost/log/detail/footer.hpp>
  125. #endif // BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_