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