]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | */ | |
65 | abstract_ordering() : FunT() | |
66 | { | |
67 | } | |
68 | /*! | |
69 | * Initializing constructor. Constructs \c FunT instance as a copy of the \a fun argument. | |
70 | */ | |
71 | explicit abstract_ordering(FunT const& fun) : FunT(fun) | |
72 | { | |
73 | } | |
74 | ||
75 | /*! | |
76 | * Ordering operator | |
77 | */ | |
78 | 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 | ||
111 | 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 > | |
117 | 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 | ||
134 | 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 > | |
140 | 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 | */ | |
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 | */ | |
171 | 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 > | |
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 > | |
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_ |