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