counter.hpp 5.1 KB

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