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