record_ordering.hpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 record_ordering.hpp
  9. * \author Andrey Semashev
  10. * \date 23.08.2009
  11. *
  12. * This header contains ordering predicates for logging records.
  13. */
  14. #ifndef BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
  15. #define BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_
  16. #include <boost/core/enable_if.hpp>
  17. #include <boost/type_traits/is_same.hpp>
  18. #include <boost/log/detail/config.hpp>
  19. #include <boost/log/detail/function_traits.hpp>
  20. #include <boost/log/core/record_view.hpp>
  21. #include <boost/log/attributes/attribute_name.hpp>
  22. #include <boost/log/attributes/attribute_value.hpp>
  23. #include <boost/log/attributes/value_visitation.hpp>
  24. #include <boost/log/utility/functional/logical.hpp>
  25. #include <boost/log/utility/functional/nop.hpp>
  26. #include <boost/log/detail/header.hpp>
  27. #ifdef BOOST_HAS_PRAGMA_ONCE
  28. #pragma once
  29. #endif
  30. namespace boost {
  31. BOOST_LOG_OPEN_NAMESPACE
  32. /*!
  33. * \brief Ordering predicate, based on opaque pointers to the record view implementation data
  34. *
  35. * Since record views only refer to a shared implementation data, this predicate is able to order the views
  36. * by comparing the pointers to the data. Therefore two views are considered to be equivalent if they
  37. * refer to the same implementation data. Otherwise it is not specified whether one record is ordered before
  38. * the other until the predicate is applied. Note that the ordering may change every time the application runs.
  39. *
  40. * This kind of ordering may be useful if log records are to be stored in an associative
  41. * container with as least performance overhead as possible, when the particular order is not important.
  42. *
  43. * The \c FunT template argument is the predicate that is used to actually compare pointers. It should be
  44. * able to compare <tt>const void*</tt> pointers. The compared pointers may refer to distinct memory regions,
  45. * the pointers must not be interpreted in any way.
  46. */
  47. template< typename FunT = less >
  48. class abstract_ordering :
  49. private FunT
  50. {
  51. public:
  52. //! Result type
  53. typedef bool result_type;
  54. public:
  55. /*!
  56. * Default constructor. Requires \c FunT to be default constructible.
  57. */
  58. abstract_ordering() : FunT()
  59. {
  60. }
  61. /*!
  62. * Initializing constructor. Constructs \c FunT instance as a copy of the \a fun argument.
  63. */
  64. explicit abstract_ordering(FunT const& fun) : FunT(fun)
  65. {
  66. }
  67. /*!
  68. * Ordering operator
  69. */
  70. result_type operator() (record_view const& left, record_view const& right) const
  71. {
  72. // We rely on the fact that the attribute_values() method returns a reference to the object in the record implementation,
  73. // so we can compare pointers.
  74. return FunT::operator() (static_cast< const void* >(&left.attribute_values()), static_cast< const void* >(&right.attribute_values()));
  75. }
  76. };
  77. /*!
  78. * \brief Ordering predicate, based on attribute values associated with records
  79. *
  80. * This predicate allows to order log records based on values of a specifically named attribute
  81. * associated with them. Two given log records being compared should both have the specified
  82. * attribute value of the specified type to be able to be ordered properly. As a special case,
  83. * if neither of the records have the value, these records are considered equivalent. Otherwise,
  84. * the ordering results are unspecified.
  85. */
  86. template< typename ValueT, typename FunT = less >
  87. class attribute_value_ordering :
  88. private FunT
  89. {
  90. public:
  91. //! Result type
  92. typedef bool result_type;
  93. //! Compared attribute value type
  94. typedef ValueT value_type;
  95. private:
  96. template< typename LeftT >
  97. struct l2_visitor
  98. {
  99. typedef void result_type;
  100. l2_visitor(FunT const& fun, LeftT const& left, bool& result) :
  101. m_fun(fun), m_left(left), m_result(result)
  102. {
  103. }
  104. template< typename RightT >
  105. result_type operator() (RightT const& right) const
  106. {
  107. m_result = m_fun(m_left, right);
  108. }
  109. private:
  110. FunT const& m_fun;
  111. LeftT const& m_left;
  112. bool& m_result;
  113. };
  114. struct l1_visitor;
  115. friend struct l1_visitor;
  116. struct l1_visitor
  117. {
  118. typedef void result_type;
  119. l1_visitor(attribute_value_ordering const& owner, record_view const& right, bool& result) :
  120. m_owner(owner), m_right(right), m_result(result)
  121. {
  122. }
  123. template< typename LeftT >
  124. result_type operator() (LeftT const& left) const
  125. {
  126. boost::log::visit< value_type >(m_owner.m_name, m_right, l2_visitor< LeftT >(static_cast< FunT const& >(m_owner), left, m_result));
  127. }
  128. private:
  129. attribute_value_ordering const& m_owner;
  130. record_view const& m_right;
  131. bool& m_result;
  132. };
  133. private:
  134. //! Attribute value name
  135. const attribute_name m_name;
  136. public:
  137. /*!
  138. * Initializing constructor.
  139. *
  140. * \param name The attribute value name to be compared
  141. * \param fun The ordering functor
  142. */
  143. explicit attribute_value_ordering(attribute_name const& name, FunT const& fun = FunT()) :
  144. FunT(fun),
  145. m_name(name)
  146. {
  147. }
  148. /*!
  149. * Ordering operator
  150. */
  151. result_type operator() (record_view const& left, record_view const& right) const
  152. {
  153. bool result = false;
  154. if (!boost::log::visit< value_type >(m_name, left, l1_visitor(*this, right, result)))
  155. {
  156. return !boost::log::visit< value_type >(m_name, right, nop());
  157. }
  158. return result;
  159. }
  160. };
  161. /*!
  162. * The function constructs a log record ordering predicate
  163. */
  164. template< typename ValueT, typename FunT >
  165. inline attribute_value_ordering< ValueT, FunT > make_attr_ordering(attribute_name const& name, FunT const& fun)
  166. {
  167. typedef attribute_value_ordering< ValueT, FunT > ordering_t;
  168. return ordering_t(name, fun);
  169. }
  170. #if !defined(BOOST_LOG_NO_FUNCTION_TRAITS)
  171. namespace aux {
  172. //! An ordering predicate constructor that uses SFINAE to disable invalid instantiations
  173. template<
  174. typename FunT,
  175. typename ArityCheckT = typename boost::enable_if_c< aux::arity_of< FunT >::value == 2 >::type,
  176. typename Arg1T = typename aux::first_argument_type_of< FunT >::type,
  177. typename Arg2T = typename aux::second_argument_type_of< FunT >::type,
  178. typename ArgsCheckT = typename boost::enable_if_c< is_same< Arg1T, Arg2T >::value >::type
  179. >
  180. struct make_attr_ordering_type
  181. {
  182. typedef attribute_value_ordering< Arg1T, FunT > type;
  183. };
  184. } // namespace aux
  185. /*!
  186. * The function constructs a log record ordering predicate
  187. */
  188. template< typename FunT >
  189. inline typename aux::make_attr_ordering_type< FunT >::type make_attr_ordering(attribute_name const& name, FunT const& fun)
  190. {
  191. typedef typename aux::make_attr_ordering_type< FunT >::type ordering_t;
  192. return ordering_t(name, fun);
  193. }
  194. #endif // BOOST_LOG_NO_FUNCTION_TRAITS
  195. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  196. } // namespace boost
  197. #include <boost/log/detail/footer.hpp>
  198. #endif // BOOST_LOG_UTILITY_RECORD_ORDERING_HPP_INCLUDED_