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 mutable_constant.hpp Chris@16: * \author Andrey Semashev Chris@16: * \date 06.11.2007 Chris@16: * Chris@16: * The header contains implementation of a mutable constant attribute. Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_ Chris@16: #define BOOST_LOG_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_ Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #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 attributes { Chris@16: Chris@16: /*! Chris@16: * \brief A class of an attribute that holds a single constant value with ability to change it Chris@16: * Chris@16: * The mutable_constant attribute stores a single value of type, specified as the first template argument. Chris@16: * This value is returned on each attribute value acquisition. Chris@16: * Chris@16: * The attribute also allows to modify the stored value, even if the attribute is registered in an attribute set. Chris@16: * In order to ensure thread safety of such modifications the \c mutable_constant class is also parametrized Chris@16: * with three additional template arguments: mutex type, scoped write and scoped read lock types. If not specified, Chris@16: * the lock types are automatically deduced based on the mutex type. Chris@16: * Chris@16: * The implementation may avoid using these types to actually create and use the mutex, if a more efficient synchronization method is Chris@16: * available (such as atomic operations on the value type). By default no synchronization is done. Chris@16: */ Chris@16: #ifdef BOOST_LOG_DOXYGEN_PASS Chris@16: template< typename T, typename MutexT = void, typename ScopedWriteLockT = auto, typename ScopedReadLockT = auto > Chris@16: #else // BOOST_LOG_DOXYGEN_PASS Chris@16: template< Chris@16: typename T, Chris@16: typename MutexT = void, Chris@16: typename ScopedWriteLockT = Chris@16: #ifndef BOOST_LOG_NO_THREADS Chris@16: typename mpl::if_c< Chris@16: boost::log::aux::is_exclusively_lockable< MutexT >::value, Chris@16: boost::log::aux::exclusive_lock_guard< MutexT >, Chris@16: void Chris@16: >::type, Chris@16: #else Chris@16: void, Chris@16: #endif // BOOST_LOG_NO_THREADS Chris@16: typename ScopedReadLockT = Chris@16: #ifndef BOOST_LOG_NO_THREADS Chris@16: typename mpl::if_c< Chris@16: boost::log::aux::is_shared_lockable< MutexT >::value, Chris@16: boost::log::aux::shared_lock_guard< MutexT >, Chris@16: ScopedWriteLockT Chris@16: >::type Chris@16: #else Chris@16: ScopedWriteLockT Chris@16: #endif // BOOST_LOG_NO_THREADS Chris@16: #endif // BOOST_LOG_DOXYGEN_PASS Chris@16: > Chris@16: class mutable_constant : Chris@16: public attribute Chris@16: { Chris@16: public: Chris@16: //! The attribute value type Chris@16: typedef T value_type; Chris@16: Chris@16: protected: Chris@16: //! Factory implementation Chris@16: class BOOST_SYMBOL_VISIBLE impl : Chris@16: public attribute::impl Chris@16: { Chris@16: private: Chris@16: //! Mutex type Chris@16: typedef MutexT mutex_type; Chris@16: //! Shared lock type Chris@16: typedef ScopedReadLockT scoped_read_lock; Chris@16: //! Exclusive lock type Chris@16: typedef ScopedWriteLockT scoped_write_lock; Chris@16: BOOST_STATIC_ASSERT_MSG(!(is_void< mutex_type >::value || is_void< scoped_read_lock >::value || is_void< scoped_write_lock >::value), "Boost.Log: Mutex and both lock types either must not be void or must all be void"); Chris@16: //! Attribute value wrapper Chris@16: typedef attribute_value_impl< value_type > attr_value; Chris@16: Chris@16: private: Chris@16: //! Thread protection mutex Chris@16: mutable mutex_type m_Mutex; Chris@16: //! Pointer to the actual attribute value Chris@16: intrusive_ptr< attr_value > m_Value; Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Initializing constructor Chris@16: */ Chris@16: explicit impl(value_type const& value) : m_Value(new attr_value(value)) Chris@16: { Chris@16: } Chris@16: /*! Chris@16: * Initializing constructor Chris@16: */ Chris@16: explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value))) Chris@16: { Chris@16: } Chris@16: Chris@16: attribute_value get_value() Chris@16: { Chris@16: scoped_read_lock lock(m_Mutex); Chris@16: return attribute_value(m_Value); Chris@16: } Chris@16: Chris@16: void set(value_type const& value) Chris@16: { Chris@16: intrusive_ptr< attr_value > p = new attr_value(value); Chris@16: scoped_write_lock lock(m_Mutex); Chris@16: m_Value.swap(p); Chris@16: } Chris@16: Chris@16: void set(BOOST_RV_REF(value_type) value) Chris@16: { Chris@16: intrusive_ptr< attr_value > p = new attr_value(boost::move(value)); Chris@16: scoped_write_lock lock(m_Mutex); Chris@16: m_Value.swap(p); Chris@16: } Chris@16: Chris@16: value_type get() const Chris@16: { Chris@16: scoped_read_lock lock(m_Mutex); Chris@16: return m_Value->get(); Chris@16: } Chris@16: }; Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Constructor with the stored value initialization Chris@16: */ Chris@16: explicit mutable_constant(value_type const& value) : attribute(new impl(value)) Chris@16: { Chris@16: } Chris@16: /*! Chris@16: * Constructor with the stored value initialization Chris@16: */ Chris@16: explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value))) Chris@16: { Chris@16: } Chris@16: /*! Chris@16: * Constructor for casting support Chris@16: */ Chris@16: explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >()) Chris@16: { Chris@16: } Chris@16: Chris@16: /*! Chris@16: * The method sets a new attribute value. The implementation exclusively locks the mutex in order Chris@16: * to protect the value assignment. Chris@16: */ Chris@16: void set(value_type const& value) Chris@16: { Chris@16: get_impl()->set(value); Chris@16: } Chris@16: Chris@16: /*! Chris@16: * The method sets a new attribute value. Chris@16: */ Chris@16: void set(BOOST_RV_REF(value_type) value) Chris@16: { Chris@16: get_impl()->set(boost::move(value)); Chris@16: } Chris@16: Chris@16: /*! Chris@16: * The method acquires the current attribute value. The implementation non-exclusively locks the mutex in order Chris@16: * to protect the value acquisition. Chris@16: */ Chris@16: value_type get() const Chris@16: { Chris@16: return get_impl()->get(); Chris@16: } Chris@16: Chris@16: protected: Chris@16: /*! Chris@16: * \returns Pointer to the factory implementation Chris@16: */ Chris@16: impl* get_impl() const Chris@16: { Chris@16: return static_cast< impl* >(attribute::get_impl()); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: /*! Chris@16: * \brief Specialization for unlocked case Chris@16: * Chris@16: * This version of attribute does not perform thread synchronization to access the stored value. Chris@16: */ Chris@16: template< typename T > Chris@16: class mutable_constant< T, void, void, void > : Chris@16: public attribute Chris@16: { Chris@16: public: Chris@16: //! The attribute value type Chris@16: typedef T value_type; Chris@16: Chris@16: protected: Chris@16: //! Factory implementation Chris@16: class BOOST_SYMBOL_VISIBLE impl : Chris@16: public attribute::impl Chris@16: { Chris@16: private: Chris@16: //! Attribute value wrapper Chris@16: typedef attribute_value_impl< value_type > attr_value; Chris@16: Chris@16: private: Chris@16: //! The actual value Chris@16: intrusive_ptr< attr_value > m_Value; Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Initializing constructor Chris@16: */ Chris@16: explicit impl(value_type const& value) : m_Value(new attr_value(value)) Chris@16: { Chris@16: } Chris@16: /*! Chris@16: * Initializing constructor Chris@16: */ Chris@16: explicit impl(BOOST_RV_REF(value_type) value) : m_Value(new attr_value(boost::move(value))) Chris@16: { Chris@16: } Chris@16: Chris@16: attribute_value get_value() Chris@16: { Chris@16: return attribute_value(m_Value); Chris@16: } Chris@16: Chris@16: void set(value_type const& value) Chris@16: { Chris@16: m_Value = new attr_value(value); Chris@16: } Chris@16: void set(BOOST_RV_REF(value_type) value) Chris@16: { Chris@16: m_Value = new attr_value(boost::move(value)); Chris@16: } Chris@16: Chris@16: value_type get() const Chris@16: { Chris@16: return m_Value->get(); Chris@16: } Chris@16: }; Chris@16: Chris@16: public: Chris@16: /*! Chris@16: * Constructor with the stored value initialization Chris@16: */ Chris@16: explicit mutable_constant(value_type const& value) : attribute(new impl(value)) Chris@16: { Chris@16: } Chris@16: /*! Chris@16: * Constructor with the stored value initialization Chris@16: */ Chris@16: explicit mutable_constant(BOOST_RV_REF(value_type) value) : attribute(new impl(boost::move(value))) Chris@16: { Chris@16: } Chris@16: /*! Chris@16: * Constructor for casting support Chris@16: */ Chris@16: explicit mutable_constant(cast_source const& source) : attribute(source.as< impl >()) Chris@16: { Chris@16: } Chris@16: Chris@16: /*! Chris@16: * The method sets a new attribute value. Chris@16: */ Chris@16: void set(value_type const& value) Chris@16: { Chris@16: get_impl()->set(value); Chris@16: } Chris@16: Chris@16: /*! Chris@16: * The method sets a new attribute value. Chris@16: */ Chris@16: void set(BOOST_RV_REF(value_type) value) Chris@16: { Chris@16: get_impl()->set(boost::move(value)); Chris@16: } Chris@16: Chris@16: /*! Chris@16: * The method acquires the current attribute value. Chris@16: */ Chris@16: value_type get() const Chris@16: { Chris@16: return get_impl()->get(); Chris@16: } Chris@16: Chris@16: protected: Chris@16: /*! Chris@16: * \returns Pointer to the factory implementation Chris@16: */ Chris@16: impl* get_impl() const Chris@16: { Chris@16: return static_cast< impl* >(attribute::get_impl()); Chris@16: } Chris@16: }; Chris@16: Chris@16: } // namespace attributes 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_ATTRIBUTES_MUTABLE_CONSTANT_HPP_INCLUDED_