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/detail/atomic_count.hpp> 26 #endif // BOOST_LOG_NO_THREADS 27 #include <boost/log/detail/header.hpp> 28 29 #ifdef BOOST_HAS_PRAGMA_ONCE 30 #pragma once 31 #endif 32 33 namespace boost { 34 35 BOOST_LOG_OPEN_NAMESPACE 36 37 namespace attributes { 38 39 /*! 40 * \brief A class of an attribute that counts an integral value 41 * 42 * This type of attribute acts as a counter, that is, it returns a monotonously 43 * changing value each time requested. The attribute value type can be specified 44 * as a template parameter. However, the type must be an integral type of size no 45 * more than <tt>sizeof(long)</tt>. 46 */ 47 template< typename T > 48 class counter : 49 public attribute 50 { 51 // For now only integral types up to long are supported 52 BOOST_STATIC_ASSERT_MSG(is_integral< T >::value && sizeof(T) <= sizeof(long), "Boost.Log: Only integral types up to long are supported by counter attribute"); 53 54 public: 55 //! A counter value type 56 typedef T value_type; 57 58 protected: 59 //! Base class for factory implementation 60 class BOOST_LOG_NO_VTABLE BOOST_SYMBOL_VISIBLE impl : 61 public attribute::impl 62 { 63 }; 64 65 //! Generic factory implementation 66 class impl_generic; 67 #ifndef BOOST_LOG_NO_THREADS 68 //! Increment-by-one factory implementation 69 class impl_inc; 70 //! Decrement-by-one factory implementation 71 class impl_dec; 72 #endif 73 74 public: 75 /*! 76 * Constructor 77 * 78 * \param initial Initial value of the counter 79 * \param step Changing step of the counter. Each value acquired from the attribute 80 * will be greater than the previous one to this amount. 81 */ counter(value_type initial=(value_type)0,long step=1)82 explicit counter(value_type initial = (value_type)0, long step = 1) : 83 #ifndef BOOST_LOG_NO_THREADS 84 attribute() 85 { 86 if (step == 1) 87 this->set_impl(new impl_inc(initial)); 88 else if (step == -1) 89 this->set_impl(new impl_dec(initial)); 90 else 91 this->set_impl(new impl_generic(initial, step)); 92 } 93 #else 94 attribute(new impl_generic(initial, step)) 95 { 96 } 97 #endif 98 /*! 99 * Constructor for casting support 100 */ counter(cast_source const & source)101 explicit counter(cast_source const& source) : 102 attribute(source.as< impl >()) 103 { 104 } 105 }; 106 107 #ifndef BOOST_LOG_NO_THREADS 108 109 template< typename T > 110 class counter< T >::impl_generic : 111 public impl 112 { 113 private: 114 //! Initial value 115 const value_type m_Initial; 116 //! Step value 117 const long m_Step; 118 //! The counter 119 boost::detail::atomic_count m_Counter; 120 121 public: 122 /*! 123 * Initializing constructor 124 */ impl_generic(value_type initial,long step)125 impl_generic(value_type initial, long step) : m_Initial(initial), m_Step(step), m_Counter(-1) 126 { 127 } 128 get_value()129 attribute_value get_value() 130 { 131 const unsigned long next_counter = static_cast< unsigned long >(++m_Counter); 132 value_type next = static_cast< value_type >(m_Initial + (next_counter * m_Step)); 133 return make_attribute_value(next); 134 } 135 }; 136 137 template< typename T > 138 class counter< T >::impl_inc : 139 public impl 140 { 141 private: 142 //! The counter 143 boost::detail::atomic_count m_Counter; 144 145 public: 146 /*! 147 * Initializing constructor 148 */ impl_inc(value_type initial)149 explicit impl_inc(value_type initial) : m_Counter(initial - 1) 150 { 151 } 152 get_value()153 attribute_value get_value() 154 { 155 return make_attribute_value(static_cast< value_type >(++m_Counter)); 156 } 157 }; 158 159 template< typename T > 160 class counter< T >::impl_dec : 161 public impl 162 { 163 private: 164 //! The counter 165 boost::detail::atomic_count m_Counter; 166 167 public: 168 /*! 169 * Initializing constructor 170 */ impl_dec(value_type initial)171 explicit impl_dec(value_type initial) : m_Counter(initial + 1) 172 { 173 } 174 get_value()175 attribute_value get_value() 176 { 177 return make_attribute_value(static_cast< value_type >(--m_Counter)); 178 } 179 }; 180 181 #else // BOOST_LOG_NO_THREADS 182 183 template< typename T > 184 class counter< T >::impl_generic : 185 public impl 186 { 187 private: 188 //! Step value 189 const long m_Step; 190 //! The counter 191 value_type m_Counter; 192 193 public: 194 /*! 195 * Initializing constructor 196 */ impl_generic(value_type initial,long step)197 impl_generic(value_type initial, long step) : m_Step(step), m_Counter(initial - step) 198 { 199 } 200 get_value()201 attribute_value get_value() 202 { 203 m_Counter += m_Step; 204 return make_attribute_value(m_Counter); 205 } 206 }; 207 208 #endif // BOOST_LOG_NO_THREADS 209 210 } // namespace attributes 211 212 BOOST_LOG_CLOSE_NAMESPACE // namespace log 213 214 } // namespace boost 215 216 #include <boost/log/detail/footer.hpp> 217 218 #endif // BOOST_LOG_ATTRIBUTES_COUNTER_HPP_INCLUDED_ 219