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 counter.hpp 9 * \author Andrey Semashev 10 * \date 01.05.2007 11 * 12 * The header contains implementation of the counter attribute. 13 */ 14 15 #ifndef BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_ 16 #define BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_ 17 18 #include <boost/static_assert.hpp> 19 #include <boost/type_traits/is_integral.hpp> 20 #include <boost/log/detail/config.hpp> 21 #include <boost/log/attributes/attribute.hpp> 22 #include <boost/log/attributes/attribute_cast.hpp> 23 #include <boost/log/attributes/attribute_value_impl.hpp> 24 #ifndef BOOST_LOG_NO_THREADS 25 #include <boost/memory_order.hpp> 26 #include <boost/atomic/atomic.hpp> 27 #endif // BOOST_LOG_NO_THREADS 28 #include <boost/log/detail/header.hpp> 29 30 #ifdef BOOST_HAS_PRAGMA_ONCE 31 #pragma once 32 #endif 33 34 namespace boost { 35 36 BOOST_LOG_OPEN_NAMESPACE 37 38 namespace attributes { 39 40 /*! 41 * \brief A class of an attribute that counts an integral value 42 * 43 * This attribute acts as a counter - it returns a monotonously 44 * changing value each time requested. The attribute value type can be specified 45 * as a template parameter. The type must be an integral type. 46 */ 47 template< typename T > 48 class counter : 49 public attribute 50 { 51 BOOST_STATIC_ASSERT_MSG(is_integral< T >::value, "Boost.Log: Only integral types are supported by the counter attribute"); 52 53 public: 54 //! A counter value type 55 typedef T value_type; 56 57 protected: 58 //! Factory implementation 59 class BOOST_SYMBOL_VISIBLE impl : 60 public attribute::impl 61 { 62 private: 63 #ifndef BOOST_LOG_NO_THREADS 64 boost::atomic< value_type > m_counter; 65 #else 66 value_type m_counter; 67 #endif 68 const value_type m_step; 69 70 public: impl(value_type initial,value_type step)71 impl(value_type initial, value_type step) BOOST_NOEXCEPT : 72 m_counter(initial), m_step(step) 73 { 74 } 75 get_value()76 attribute_value get_value() 77 { 78 #ifndef BOOST_LOG_NO_THREADS 79 value_type value = m_counter.fetch_add(m_step, boost::memory_order_relaxed); 80 #else 81 value_type value = m_counter; 82 m_counter += m_step; 83 #endif 84 return make_attribute_value(value); 85 } 86 }; 87 88 public: 89 /*! 90 * Constructor 91 * 92 * \param initial Initial value of the counter 93 * \param step Changing step of the counter. Each value acquired from the attribute 94 * will be greater than the previous one by this amount. 95 */ counter(value_type initial=(value_type)0,value_type step=(value_type)1)96 explicit counter(value_type initial = (value_type)0, value_type step = (value_type)1) : 97 attribute(new impl(initial, step)) 98 { 99 } 100 101 /*! 102 * Constructor for casting support 103 */ counter(cast_source const & source)104 explicit counter(cast_source const& source) : 105 attribute(source.as< impl >()) 106 { 107 } 108 }; 109 110 } // namespace attributes 111 112 BOOST_LOG_CLOSE_NAMESPACE // namespace log 113 114 } // namespace boost 115 116 #include <boost/log/detail/footer.hpp> 117 118 #endif // BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_ 119