text: /*
   *          Copyright Andrey Semashev 2007 - 2015.
   * Distributed under the Boost Software License, Version 1.0.
   *    (See accompanying file LICENSE_1_0.txt or copy at
   *          http://www.boost.org/LICENSE_1_0.txt)
   */
  /*!
   * \file   locking_ptr.hpp
   * \author Andrey Semashev
   * \date   15.07.2009
   *
   * This header is the Boost.Log library implementation, see the library documentation
   * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
   */
  
  #ifndef BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
  #define BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
  
  #include <cstddef>
  #include <boost/move/core.hpp>
  #include <boost/smart_ptr/shared_ptr.hpp>
  #include <boost/thread/lock_options.hpp>
  #include <boost/log/detail/config.hpp>
  #include <boost/utility/explicit_operator_bool.hpp>
  #include <boost/log/detail/header.hpp>
  
  #ifdef BOOST_HAS_PRAGMA_ONCE
  #pragma once
  #endif
  
  namespace boost {
  
  BOOST_LOG_OPEN_NAMESPACE
  
  namespace aux {
  
  //! A pointer type that locks the backend until it's destroyed
  template< typename T, typename LockableT >
  class locking_ptr
  {
      typedef locking_ptr this_type;
      BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
  
  public:
      //! Pointed type
      typedef T element_type;
  
  private:
      //! Lockable type
      typedef LockableT lockable_type;
  
  private:
      //! The pointer to the backend
      shared_ptr< element_type > m_pElement;
      //! Reference to the shared lock control object
      lockable_type* m_pLock;
  
  public:
      //! Default constructor
      locking_ptr() BOOST_NOEXCEPT : m_pLock(NULL)
      {
      }
      //! Constructor
      locking_ptr(shared_ptr< element_type > const& p, lockable_type& l) : m_pElement(p), m_pLock(&l)
      {
          m_pLock->lock();
      }
      //! Constructor
      locking_ptr(shared_ptr< element_type > const& p, lockable_type& l, try_to_lock_t const&) : m_pElement(p), m_pLock(&l)
      {
          if (!m_pLock->try_lock())
          {
              m_pElement.reset();
              m_pLock = NULL;
          }
      }
      //! Copy constructor
      locking_ptr(locking_ptr const& that) : m_pElement(that.m_pElement), m_pLock(that.m_pLock)
      {
          if (m_pLock)
              m_pLock->lock();
      }
      //! Move constructor
      locking_ptr(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT : m_pLock(that.m_pLock)
      {
          m_pElement.swap(that.m_pElement);
          that.m_pLock = NULL;
      }
  
      //! Destructor
      ~locking_ptr()
      {
          if (m_pLock)
              m_pLock->unlock();
      }
  
      //! Assignment
      locking_ptr& operator= (locking_ptr that) BOOST_NOEXCEPT
      {
          this->swap(that);
          return *this;
      }
  
      //! Indirection
      element_type* operator-> () const BOOST_NOEXCEPT { return m_pElement.get(); }
      //! Dereferencing
      element_type& operator* () const BOOST_NOEXCEPT { return *m_pElement; }
  
      //! Accessor to the raw pointer
      element_type* get() const BOOST_NOEXCEPT { return m_pElement.get(); }
  
      //! Checks for null pointer
      BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
      //! Checks for null pointer
      bool operator! () const BOOST_NOEXCEPT { return !m_pElement; }
  
      //! Swaps two pointers
      void swap(locking_ptr& that) BOOST_NOEXCEPT
      {
          m_pElement.swap(that.m_pElement);
          lockable_type* p = m_pLock;
          m_pLock = that.m_pLock;
          that.m_pLock = p;
      }
  };
  
  //! Free raw pointer getter to assist generic programming
  template< typename T, typename LockableT >
  inline T* get_pointer(locking_ptr< T, LockableT > const& p) BOOST_NOEXCEPT
  {
      return p.get();
  }
  //! Free swap operation
  template< typename T, typename LockableT >
  inline void swap(locking_ptr< T, LockableT >& left, locking_ptr< T, LockableT >& right) BOOST_NOEXCEPT
  {
      left.swap(right);
  }
  
  } // namespace aux
  
  BOOST_LOG_CLOSE_NAMESPACE // namespace log
  
  } // namespace boost
  
  #include <boost/log/detail/footer.hpp>
  
  #endif // BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_
  