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 attribute.hpp 9 * \author Andrey Semashev 10 * \date 15.04.2007 11 * 12 * The header contains attribute interface definition. 13 */ 14 15 #ifndef BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_ 16 #define BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_ 17 18 #include <new> 19 #include <boost/move/core.hpp> 20 #include <boost/smart_ptr/intrusive_ptr.hpp> 21 #include <boost/smart_ptr/intrusive_ref_counter.hpp> 22 #include <boost/core/explicit_operator_bool.hpp> 23 #include <boost/log/detail/config.hpp> 24 #include <boost/log/detail/header.hpp> 25 26 #ifdef BOOST_HAS_PRAGMA_ONCE 27 #pragma once 28 #endif 29 30 namespace boost { 31 32 BOOST_LOG_OPEN_NAMESPACE 33 34 #ifndef BOOST_LOG_DOXYGEN_PASS 35 36 class attribute_value; 37 38 namespace aux { 39 40 //! Reference proxy object to implement \c operator[] 41 class attribute_set_reference_proxy; 42 43 } // namespace aux 44 45 #endif // BOOST_LOG_DOXYGEN_PASS 46 47 /*! 48 * \brief A base class for an attribute value factory 49 * 50 * Every attribute is represented with a factory that is basically an attribute value generator. 51 * The sole purpose of an attribute is to return an actual value when requested. A simplest attribute 52 * can always return the same value that it stores internally, but more complex ones can 53 * perform a considerable amount of work to return a value, and the returned values may differ 54 * each time requested. 55 * 56 * A word about thread safety. An attribute should be prepared to be requested a value from 57 * multiple threads concurrently. 58 */ 59 class attribute 60 { 61 BOOST_COPYABLE_AND_MOVABLE(attribute) 62 63 public: 64 /*! 65 * \brief A base class for an attribute value factory 66 * 67 * All attributes must derive their implementation from this class. 68 */ 69 struct BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE impl : 70 public boost::intrusive_ref_counter< impl > 71 { 72 /*! 73 * \brief Virtual destructor 74 */ ~implboost::attribute::impl75 virtual ~impl() {} 76 77 /*! 78 * \return The actual attribute value. It shall not return empty values (exceptions 79 * shall be used to indicate errors). 80 */ 81 virtual attribute_value get_value() = 0; 82 83 BOOST_LOG_API static void* operator new (std::size_t size); 84 BOOST_LOG_API static void operator delete (void* p, std::size_t size) BOOST_NOEXCEPT; 85 }; 86 87 private: 88 //! Pointer to the attribute factory implementation 89 intrusive_ptr< impl > m_pImpl; 90 91 public: 92 /*! 93 * Default constructor. Creates an empty attribute value factory, which is not usable until 94 * \c set_impl is called. 95 */ attribute()96 BOOST_DEFAULTED_FUNCTION(attribute(), {}) 97 98 /*! 99 * Copy constructor 100 */ 101 attribute(attribute const& that) BOOST_NOEXCEPT : m_pImpl(that.m_pImpl) {} 102 103 /*! 104 * Move constructor 105 */ attribute(BOOST_RV_REF (attribute)that)106 attribute(BOOST_RV_REF(attribute) that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); } 107 108 /*! 109 * Initializing constructor 110 * 111 * \param p Pointer to the implementation. Must not be \c NULL. 112 */ attribute(intrusive_ptr<impl> p)113 explicit attribute(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); } 114 115 /*! 116 * Copy assignment 117 */ operator =(BOOST_COPY_ASSIGN_REF (attribute)that)118 attribute& operator= (BOOST_COPY_ASSIGN_REF(attribute) that) BOOST_NOEXCEPT 119 { 120 m_pImpl = that.m_pImpl; 121 return *this; 122 } 123 124 /*! 125 * Move assignment 126 */ operator =(BOOST_RV_REF (attribute)that)127 attribute& operator= (BOOST_RV_REF(attribute) that) BOOST_NOEXCEPT 128 { 129 m_pImpl.swap(that.m_pImpl); 130 return *this; 131 } 132 133 #ifndef BOOST_LOG_DOXYGEN_PASS 134 attribute& operator= (aux::attribute_set_reference_proxy const& that) BOOST_NOEXCEPT; 135 #endif 136 137 /*! 138 * Verifies that the factory is not in empty state 139 */ 140 BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() 141 142 /*! 143 * Verifies that the factory is in empty state 144 */ 145 bool operator! () const BOOST_NOEXCEPT { return !m_pImpl; } 146 147 /*! 148 * \return The actual attribute value. It shall not return empty values (exceptions 149 * shall be used to indicate errors). 150 */ 151 attribute_value get_value() const; 152 153 /*! 154 * The method swaps two factories (i.e. their implementations). 155 */ swap(attribute & that)156 void swap(attribute& that) BOOST_NOEXCEPT { m_pImpl.swap(that.m_pImpl); } 157 158 protected: 159 /*! 160 * \returns The pointer to the implementation 161 */ get_impl() const162 impl* get_impl() const BOOST_NOEXCEPT { return m_pImpl.get(); } 163 /*! 164 * Sets the pointer to the factory implementation. 165 * 166 * \param p Pointer to the implementation. Must not be \c NULL. 167 */ set_impl(intrusive_ptr<impl> p)168 void set_impl(intrusive_ptr< impl > p) BOOST_NOEXCEPT { m_pImpl.swap(p); } 169 170 template< typename T > 171 friend T attribute_cast(attribute const&); 172 }; 173 174 /*! 175 * The function swaps two attribute value factories 176 */ swap(attribute & left,attribute & right)177inline void swap(attribute& left, attribute& right) BOOST_NOEXCEPT 178 { 179 left.swap(right); 180 } 181 182 BOOST_LOG_CLOSE_NAMESPACE // namespace log 183 184 } // namespace boost 185 186 #include <boost/log/detail/footer.hpp> 187 #if defined(BOOST_LOG_ATTRIBUTES_ATTRIBUTE_VALUE_HPP_INCLUDED_) 188 #include <boost/log/detail/attribute_get_value_impl.hpp> 189 #endif 190 191 #endif // BOOST_LOG_ATTRIBUTES_ATTRIBUTE_HPP_INCLUDED_ 192