Chris@16
|
1 /*
|
Chris@101
|
2 * Copyright Andrey Semashev 2007 - 2015.
|
Chris@16
|
3 * Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 * (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 */
|
Chris@16
|
7 /*!
|
Chris@16
|
8 * \file exception_handler.hpp
|
Chris@16
|
9 * \author Andrey Semashev
|
Chris@16
|
10 * \date 12.07.2009
|
Chris@16
|
11 *
|
Chris@16
|
12 * This header contains tools for exception handlers support in different parts of the library.
|
Chris@16
|
13 */
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
|
Chris@16
|
16 #define BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
|
Chris@16
|
17
|
Chris@101
|
18 #include <new> // std::nothrow_t
|
Chris@16
|
19 #include <boost/mpl/bind.hpp>
|
Chris@16
|
20 #include <boost/mpl/quote.hpp>
|
Chris@16
|
21 #include <boost/mpl/fold.hpp>
|
Chris@16
|
22 #include <boost/mpl/placeholders.hpp>
|
Chris@16
|
23 #include <boost/mpl/has_xxx.hpp>
|
Chris@16
|
24 #include <boost/mpl/vector.hpp>
|
Chris@16
|
25 #include <boost/preprocessor/cat.hpp>
|
Chris@16
|
26 #include <boost/preprocessor/repetition/enum_params.hpp>
|
Chris@16
|
27 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
Chris@16
|
28 #include <boost/utility/enable_if.hpp>
|
Chris@16
|
29 #include <boost/log/detail/config.hpp>
|
Chris@16
|
30 #include <boost/log/utility/functional/nop.hpp>
|
Chris@16
|
31 #include <boost/log/detail/header.hpp>
|
Chris@16
|
32
|
Chris@16
|
33 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@16
|
34 #pragma once
|
Chris@16
|
35 #endif
|
Chris@16
|
36
|
Chris@16
|
37 #ifndef BOOST_LOG_MAX_EXCEPTION_TYPES
|
Chris@16
|
38 //! Maximum number of exception types that can be specified for exception handlers
|
Chris@16
|
39 #define BOOST_LOG_MAX_EXCEPTION_TYPES 10
|
Chris@16
|
40 #endif
|
Chris@16
|
41
|
Chris@16
|
42 namespace boost {
|
Chris@16
|
43
|
Chris@16
|
44 BOOST_LOG_OPEN_NAMESPACE
|
Chris@16
|
45
|
Chris@16
|
46 namespace aux {
|
Chris@16
|
47
|
Chris@16
|
48 BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_exception_types, exception_types, false)
|
Chris@16
|
49
|
Chris@16
|
50 //! Root class for the exception handler class hierarchy
|
Chris@16
|
51 template< typename HandlerT >
|
Chris@16
|
52 class eh_root
|
Chris@16
|
53 {
|
Chris@16
|
54 public:
|
Chris@16
|
55 //! The exception handler type
|
Chris@16
|
56 typedef HandlerT handler_type;
|
Chris@16
|
57 //! The handler result type
|
Chris@16
|
58 typedef void result_type;
|
Chris@16
|
59
|
Chris@16
|
60 protected:
|
Chris@16
|
61 //! Exception handler
|
Chris@16
|
62 handler_type m_Handler;
|
Chris@16
|
63
|
Chris@16
|
64 public:
|
Chris@16
|
65 //! Initializing constructor
|
Chris@16
|
66 explicit eh_root(handler_type const& handler) : m_Handler(handler)
|
Chris@16
|
67 {
|
Chris@16
|
68 }
|
Chris@16
|
69
|
Chris@16
|
70 //! Exception launcher
|
Chris@16
|
71 void operator()() const
|
Chris@16
|
72 {
|
Chris@16
|
73 throw;
|
Chris@16
|
74 }
|
Chris@16
|
75 };
|
Chris@16
|
76
|
Chris@16
|
77 //! A cons-list element of the exception handler class hierarchy
|
Chris@16
|
78 template< typename ExceptionT, typename BaseT >
|
Chris@16
|
79 class eh_cons :
|
Chris@16
|
80 public BaseT
|
Chris@16
|
81 {
|
Chris@16
|
82 //! Base type
|
Chris@16
|
83 typedef BaseT base_type;
|
Chris@16
|
84
|
Chris@16
|
85 public:
|
Chris@16
|
86 //! The exception handler type
|
Chris@16
|
87 typedef typename base_type::handler_type handler_type;
|
Chris@16
|
88
|
Chris@16
|
89 public:
|
Chris@16
|
90 //! Initializing constructor
|
Chris@16
|
91 explicit eh_cons(handler_type const& handler) : base_type(handler)
|
Chris@16
|
92 {
|
Chris@16
|
93 }
|
Chris@16
|
94
|
Chris@16
|
95 //! Exception launcher
|
Chris@16
|
96 void operator()() const
|
Chris@16
|
97 {
|
Chris@16
|
98 try
|
Chris@16
|
99 {
|
Chris@16
|
100 base_type::operator()();
|
Chris@16
|
101 }
|
Chris@16
|
102 catch (ExceptionT& e)
|
Chris@16
|
103 {
|
Chris@16
|
104 this->m_Handler(e);
|
Chris@16
|
105 }
|
Chris@16
|
106 }
|
Chris@16
|
107 };
|
Chris@16
|
108
|
Chris@16
|
109 template< template< typename, typename > class EHT, typename HandlerT >
|
Chris@16
|
110 struct make_self_contained_exception_handler
|
Chris@16
|
111 {
|
Chris@16
|
112 typedef EHT< typename HandlerT::exception_types, HandlerT > type;
|
Chris@16
|
113 };
|
Chris@16
|
114
|
Chris@16
|
115 } // namespace aux
|
Chris@16
|
116
|
Chris@16
|
117 /*!
|
Chris@16
|
118 * An exception handler functional object. The handler aggregates a user-defined
|
Chris@16
|
119 * functional object that will be called when one of the specified exception types
|
Chris@16
|
120 * is caught.
|
Chris@16
|
121 */
|
Chris@16
|
122 template< typename SequenceT, typename HandlerT >
|
Chris@16
|
123 class exception_handler :
|
Chris@16
|
124 public mpl::fold<
|
Chris@16
|
125 SequenceT,
|
Chris@16
|
126 aux::eh_root< HandlerT >,
|
Chris@16
|
127 mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 >
|
Chris@16
|
128 >::type
|
Chris@16
|
129 {
|
Chris@16
|
130 //! Base type
|
Chris@16
|
131 typedef typename mpl::fold<
|
Chris@16
|
132 SequenceT,
|
Chris@16
|
133 aux::eh_root< HandlerT >,
|
Chris@16
|
134 mpl::bind< mpl::quote2< aux::eh_cons >, mpl::_2, mpl::_1 >
|
Chris@16
|
135 >::type base_type;
|
Chris@16
|
136
|
Chris@16
|
137 public:
|
Chris@16
|
138 #ifndef BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
139 typedef typename base_type::handler_type handler_type;
|
Chris@16
|
140 #else
|
Chris@16
|
141 //! The exception handler type
|
Chris@16
|
142 typedef HandlerT handler_type;
|
Chris@16
|
143 //! The handler result type
|
Chris@16
|
144 typedef void result_type;
|
Chris@16
|
145 #endif
|
Chris@16
|
146
|
Chris@16
|
147 public:
|
Chris@16
|
148 /*!
|
Chris@16
|
149 * Initializing constructor. Creates an exception handler with the specified
|
Chris@16
|
150 * function object that will receive the exception.
|
Chris@16
|
151 */
|
Chris@16
|
152 explicit exception_handler(handler_type const& handler) : base_type(handler)
|
Chris@16
|
153 {
|
Chris@16
|
154 }
|
Chris@16
|
155
|
Chris@16
|
156 /*!
|
Chris@16
|
157 * Exception launcher. Rethrows the current exception in order to detect its type
|
Chris@16
|
158 * and pass it to the aggregated function object.
|
Chris@16
|
159 *
|
Chris@16
|
160 * \note Must be called from within a \c catch statement.
|
Chris@16
|
161 */
|
Chris@16
|
162 void operator()() const
|
Chris@16
|
163 {
|
Chris@16
|
164 base_type::operator()();
|
Chris@16
|
165 }
|
Chris@16
|
166 };
|
Chris@16
|
167
|
Chris@16
|
168 /*!
|
Chris@16
|
169 * A no-throw exception handler functional object. Acts similar to \c exception_handler,
|
Chris@16
|
170 * but in case if the exception cannot be handled the exception is not propagated
|
Chris@16
|
171 * from the handler. Instead the user-defined functional object is called with
|
Chris@16
|
172 * no parameters.
|
Chris@16
|
173 */
|
Chris@16
|
174 template< typename SequenceT, typename HandlerT >
|
Chris@16
|
175 class nothrow_exception_handler :
|
Chris@16
|
176 public exception_handler< SequenceT, HandlerT >
|
Chris@16
|
177 {
|
Chris@16
|
178 //! Base type
|
Chris@16
|
179 typedef exception_handler< SequenceT, HandlerT > base_type;
|
Chris@16
|
180
|
Chris@16
|
181 public:
|
Chris@16
|
182 #ifndef BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
183 typedef typename base_type::handler_type handler_type;
|
Chris@16
|
184 #else
|
Chris@16
|
185 //! The exception handler type
|
Chris@16
|
186 typedef HandlerT handler_type;
|
Chris@16
|
187 //! The handler result type
|
Chris@16
|
188 typedef void result_type;
|
Chris@16
|
189 #endif
|
Chris@16
|
190
|
Chris@16
|
191 public:
|
Chris@16
|
192 /*!
|
Chris@16
|
193 * Initializing constructor. Creates an exception handler with the specified
|
Chris@16
|
194 * function object that will receive the exception.
|
Chris@16
|
195 */
|
Chris@16
|
196 explicit nothrow_exception_handler(handler_type const& handler) : base_type(handler)
|
Chris@16
|
197 {
|
Chris@16
|
198 }
|
Chris@16
|
199
|
Chris@16
|
200 /*!
|
Chris@16
|
201 * Exception launcher. Rethrows the current exception in order to detect its type
|
Chris@16
|
202 * and pass it to the aggregated function object. If the type of the exception
|
Chris@16
|
203 * could not be detected, the user-defined handler is called with no arguments.
|
Chris@16
|
204 *
|
Chris@16
|
205 * \note Must be called from within a \c catch statement.
|
Chris@16
|
206 */
|
Chris@16
|
207 void operator()() const
|
Chris@16
|
208 {
|
Chris@16
|
209 try
|
Chris@16
|
210 {
|
Chris@16
|
211 base_type::operator()();
|
Chris@16
|
212 }
|
Chris@16
|
213 catch (...)
|
Chris@16
|
214 {
|
Chris@16
|
215 this->m_Handler();
|
Chris@16
|
216 }
|
Chris@16
|
217 }
|
Chris@16
|
218 };
|
Chris@16
|
219
|
Chris@16
|
220 /*!
|
Chris@16
|
221 * The function creates an empty exception handler that effectively suppresses any exception
|
Chris@16
|
222 */
|
Chris@16
|
223 inline nop make_exception_suppressor()
|
Chris@16
|
224 {
|
Chris@16
|
225 return nop();
|
Chris@16
|
226 }
|
Chris@16
|
227
|
Chris@16
|
228 #ifndef BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
229
|
Chris@16
|
230 template< typename HandlerT >
|
Chris@16
|
231 inline typename lazy_enable_if<
|
Chris@16
|
232 aux::has_exception_types< HandlerT >,
|
Chris@16
|
233 aux::make_self_contained_exception_handler< exception_handler, HandlerT >
|
Chris@16
|
234 >::type make_exception_handler(HandlerT const& handler)
|
Chris@16
|
235 {
|
Chris@16
|
236 typedef typename aux::make_self_contained_exception_handler< exception_handler, HandlerT >::type eh_t;
|
Chris@16
|
237 return eh_t(handler);
|
Chris@16
|
238 }
|
Chris@16
|
239
|
Chris@16
|
240 template< typename HandlerT >
|
Chris@16
|
241 inline typename lazy_enable_if<
|
Chris@16
|
242 aux::has_exception_types< HandlerT >,
|
Chris@16
|
243 aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >
|
Chris@16
|
244 >::type make_exception_handler(HandlerT const& handler, std::nothrow_t const&)
|
Chris@16
|
245 {
|
Chris@16
|
246 typedef typename aux::make_self_contained_exception_handler< nothrow_exception_handler, HandlerT >::type eh_t;
|
Chris@16
|
247 return eh_t(handler);
|
Chris@16
|
248 }
|
Chris@16
|
249
|
Chris@16
|
250 #define BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL(z, n, data)\
|
Chris@16
|
251 template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\
|
Chris@16
|
252 inline exception_handler<\
|
Chris@16
|
253 BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
|
Chris@16
|
254 HandlerT\
|
Chris@16
|
255 > make_exception_handler(HandlerT const& handler)\
|
Chris@16
|
256 {\
|
Chris@16
|
257 typedef exception_handler<\
|
Chris@16
|
258 BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
|
Chris@16
|
259 HandlerT\
|
Chris@16
|
260 > eh_t;\
|
Chris@16
|
261 return eh_t(handler);\
|
Chris@16
|
262 }\
|
Chris@16
|
263 template< BOOST_PP_ENUM_PARAMS(n, typename T), typename HandlerT >\
|
Chris@16
|
264 inline nothrow_exception_handler<\
|
Chris@16
|
265 BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
|
Chris@16
|
266 HandlerT\
|
Chris@16
|
267 > make_exception_handler(HandlerT const& handler, std::nothrow_t const&)\
|
Chris@16
|
268 {\
|
Chris@16
|
269 typedef nothrow_exception_handler<\
|
Chris@16
|
270 BOOST_PP_CAT(mpl::vector, n)< BOOST_PP_ENUM_PARAMS(n, T) >,\
|
Chris@16
|
271 HandlerT\
|
Chris@16
|
272 > eh_t;\
|
Chris@16
|
273 return eh_t(handler);\
|
Chris@16
|
274 }
|
Chris@16
|
275
|
Chris@16
|
276 BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_EXCEPTION_TYPES, BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL, ~)
|
Chris@16
|
277
|
Chris@16
|
278 #undef BOOST_LOG_MAKE_EXCEPTION_HANDLER_INTERNAL
|
Chris@16
|
279
|
Chris@16
|
280 #else // BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
281
|
Chris@16
|
282 /*!
|
Chris@16
|
283 * The function creates an exception handler functional object. The handler will call to the
|
Chris@16
|
284 * user-specified functional object with an exception as its argument.
|
Chris@16
|
285 *
|
Chris@16
|
286 * \param handler User-defined functional object that will receive exceptions.
|
Chris@16
|
287 * \return A nullary functional object that should be called from within a \c catch statement.
|
Chris@16
|
288 *
|
Chris@16
|
289 * \note This form requires the user-defined functional object to have an \c exception_types
|
Chris@16
|
290 * nested type. This type should be an MPL sequence of all expected exception types.
|
Chris@16
|
291 */
|
Chris@16
|
292 template< typename HandlerT >
|
Chris@16
|
293 exception_handler< typename HandlerT::exception_types, HandlerT >
|
Chris@16
|
294 make_exception_handler(HandlerT const& handler);
|
Chris@16
|
295
|
Chris@16
|
296 /*!
|
Chris@16
|
297 * The function creates an exception handler functional object. The handler will call to the
|
Chris@16
|
298 * user-specified functional object with an exception as its argument. If the exception type
|
Chris@16
|
299 * cannot be identified, the handler will call the user-defined functor with no arguments,
|
Chris@16
|
300 * instead of propagating exception to the caller.
|
Chris@16
|
301 *
|
Chris@16
|
302 * \overload
|
Chris@16
|
303 *
|
Chris@16
|
304 * \param handler User-defined functional object that will receive exceptions.
|
Chris@16
|
305 * \return A nullary functional object that should be called from within a \c catch statement.
|
Chris@16
|
306 *
|
Chris@16
|
307 * \note This form requires the user-defined functional object to have an \c exception_types
|
Chris@16
|
308 * nested type. This type should be an MPL sequence of all expected exception types.
|
Chris@16
|
309 */
|
Chris@16
|
310 template< typename HandlerT >
|
Chris@16
|
311 nothrow_exception_handler< typename HandlerT::exception_types, HandlerT >
|
Chris@16
|
312 make_exception_handler(HandlerT const& handler, std::nothrow_t const&);
|
Chris@16
|
313
|
Chris@16
|
314 /*!
|
Chris@16
|
315 * The function creates an exception handler functional object. The handler will call to the
|
Chris@16
|
316 * user-specified functional object with an exception as its argument. All expected exception
|
Chris@16
|
317 * types should be specified as first template parameters explicitly, in the order they would
|
Chris@16
|
318 * be specified in a corresponding <tt>try/catch</tt> statement.
|
Chris@16
|
319 *
|
Chris@16
|
320 * \overload
|
Chris@16
|
321 *
|
Chris@16
|
322 * \param handler User-defined functional object that will receive exceptions.
|
Chris@16
|
323 * \return A nullary functional object that should be called from within a \c catch statement.
|
Chris@16
|
324 */
|
Chris@16
|
325 template< typename... ExceptionsT, typename HandlerT >
|
Chris@16
|
326 exception_handler< MPL_sequence_of_ExceptionsT, HandlerT >
|
Chris@16
|
327 make_exception_handler(HandlerT const& handler);
|
Chris@16
|
328
|
Chris@16
|
329 /*!
|
Chris@16
|
330 * The function creates an exception handler functional object. The handler will call to the
|
Chris@16
|
331 * user-specified functional object with an exception as its argument. If the exception type
|
Chris@16
|
332 * cannot be identified, the handler will call the user-defined functor with no arguments,
|
Chris@16
|
333 * instead of propagating exception to the caller. All expected exception types should be
|
Chris@16
|
334 * specified as first template parameters explicitly, in the order they would be specified in
|
Chris@16
|
335 * a corresponding <tt>try/catch</tt> statement.
|
Chris@16
|
336 *
|
Chris@16
|
337 * \overload
|
Chris@16
|
338 *
|
Chris@16
|
339 * \param handler User-defined functional object that will receive exceptions.
|
Chris@16
|
340 * \return A nullary functional object that should be called from within a \c catch statement.
|
Chris@16
|
341 */
|
Chris@16
|
342 template< typename... ExceptionsT, typename HandlerT >
|
Chris@16
|
343 nothrow_exception_handler< MPL_sequence_of_ExceptionsT, HandlerT >
|
Chris@16
|
344 make_exception_handler(HandlerT const& handler, std::nothrow_t const&);
|
Chris@16
|
345
|
Chris@16
|
346 #endif // BOOST_LOG_DOXYGEN_PASS
|
Chris@16
|
347
|
Chris@16
|
348 BOOST_LOG_CLOSE_NAMESPACE // namespace log
|
Chris@16
|
349
|
Chris@16
|
350 } // namespace boost
|
Chris@16
|
351
|
Chris@16
|
352 #include <boost/log/detail/footer.hpp>
|
Chris@16
|
353
|
Chris@16
|
354 #endif // BOOST_LOG_UTILITY_EXCEPTION_HANDLER_HPP_INCLUDED_
|