Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/log/sinks/basic_sink_frontend.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 /* | |
2 * Copyright Andrey Semashev 2007 - 2013. | |
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 basic_sink_frontend.hpp | |
9 * \author Andrey Semashev | |
10 * \date 14.07.2009 | |
11 * | |
12 * The header contains implementation of a base class for sink frontends. | |
13 */ | |
14 | |
15 #ifndef BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_ | |
16 #define BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_ | |
17 | |
18 #include <boost/mpl/bool.hpp> | |
19 #include <boost/log/detail/config.hpp> | |
20 #include <boost/log/detail/cleanup_scope_guard.hpp> | |
21 #include <boost/log/detail/code_conversion.hpp> | |
22 #include <boost/log/detail/attachable_sstream_buf.hpp> | |
23 #include <boost/log/detail/fake_mutex.hpp> | |
24 #include <boost/log/core/record_view.hpp> | |
25 #include <boost/log/sinks/sink.hpp> | |
26 #include <boost/log/sinks/frontend_requirements.hpp> | |
27 #include <boost/log/expressions/filter.hpp> | |
28 #include <boost/log/expressions/formatter.hpp> | |
29 #if !defined(BOOST_LOG_NO_THREADS) | |
30 #include <boost/thread/exceptions.hpp> | |
31 #include <boost/thread/tss.hpp> | |
32 #include <boost/thread/locks.hpp> | |
33 #include <boost/log/detail/locks.hpp> | |
34 #include <boost/log/detail/light_rw_mutex.hpp> | |
35 #include <boost/concept_check.hpp> | |
36 #endif // !defined(BOOST_LOG_NO_THREADS) | |
37 #include <boost/log/detail/header.hpp> | |
38 | |
39 #ifdef BOOST_HAS_PRAGMA_ONCE | |
40 #pragma once | |
41 #endif | |
42 | |
43 namespace boost { | |
44 | |
45 BOOST_LOG_OPEN_NAMESPACE | |
46 | |
47 namespace sinks { | |
48 | |
49 //! A base class for a logging sink frontend | |
50 class BOOST_LOG_NO_VTABLE basic_sink_frontend : | |
51 public sink | |
52 { | |
53 //! Base type | |
54 typedef sink base_type; | |
55 | |
56 public: | |
57 //! An exception handler type | |
58 typedef base_type::exception_handler_type exception_handler_type; | |
59 | |
60 #if !defined(BOOST_LOG_NO_THREADS) | |
61 protected: | |
62 //! Mutex type | |
63 typedef boost::log::aux::light_rw_mutex mutex_type; | |
64 | |
65 private: | |
66 //! Synchronization mutex | |
67 mutable mutex_type m_Mutex; | |
68 #endif | |
69 | |
70 private: | |
71 //! Filter | |
72 filter m_Filter; | |
73 //! Exception handler | |
74 exception_handler_type m_ExceptionHandler; | |
75 | |
76 public: | |
77 /*! | |
78 * \brief Initializing constructor | |
79 * | |
80 * \param cross_thread The flag indicates whether the sink passes log records between different threads | |
81 */ | |
82 explicit basic_sink_frontend(bool cross_thread) : sink(cross_thread) | |
83 { | |
84 } | |
85 | |
86 /*! | |
87 * The method sets sink-specific filter functional object | |
88 */ | |
89 template< typename FunT > | |
90 void set_filter(FunT const& filter) | |
91 { | |
92 BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);) | |
93 m_Filter = filter; | |
94 } | |
95 /*! | |
96 * The method resets the filter | |
97 */ | |
98 void reset_filter() | |
99 { | |
100 BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);) | |
101 m_Filter.reset(); | |
102 } | |
103 | |
104 /*! | |
105 * The method sets an exception handler function | |
106 */ | |
107 template< typename FunT > | |
108 void set_exception_handler(FunT const& handler) | |
109 { | |
110 BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);) | |
111 m_ExceptionHandler = handler; | |
112 } | |
113 | |
114 /*! | |
115 * The method resets the exception handler function | |
116 */ | |
117 void reset_exception_handler() | |
118 { | |
119 BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);) | |
120 m_ExceptionHandler.clear(); | |
121 } | |
122 | |
123 /*! | |
124 * The method returns \c true if no filter is set or the attribute values pass the filter | |
125 * | |
126 * \param attrs A set of attribute values of a logging record | |
127 */ | |
128 bool will_consume(attribute_value_set const& attrs) | |
129 { | |
130 BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);) | |
131 try | |
132 { | |
133 return m_Filter(attrs); | |
134 } | |
135 #if !defined(BOOST_LOG_NO_THREADS) | |
136 catch (thread_interrupted&) | |
137 { | |
138 throw; | |
139 } | |
140 #endif | |
141 catch (...) | |
142 { | |
143 if (m_ExceptionHandler.empty()) | |
144 throw; | |
145 m_ExceptionHandler(); | |
146 return false; | |
147 } | |
148 } | |
149 | |
150 protected: | |
151 #if !defined(BOOST_LOG_NO_THREADS) | |
152 //! Returns reference to the frontend mutex | |
153 mutex_type& frontend_mutex() const { return m_Mutex; } | |
154 #endif | |
155 | |
156 //! Returns reference to the exception handler | |
157 exception_handler_type& exception_handler() { return m_ExceptionHandler; } | |
158 //! Returns reference to the exception handler | |
159 exception_handler_type const& exception_handler() const { return m_ExceptionHandler; } | |
160 | |
161 //! Feeds log record to the backend | |
162 template< typename BackendMutexT, typename BackendT > | |
163 void feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) | |
164 { | |
165 try | |
166 { | |
167 BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);) | |
168 backend.consume(rec); | |
169 } | |
170 #if !defined(BOOST_LOG_NO_THREADS) | |
171 catch (thread_interrupted&) | |
172 { | |
173 throw; | |
174 } | |
175 #endif | |
176 catch (...) | |
177 { | |
178 BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);) | |
179 if (m_ExceptionHandler.empty()) | |
180 throw; | |
181 m_ExceptionHandler(); | |
182 } | |
183 } | |
184 | |
185 //! Attempts to feeds log record to the backend, does not block if \a backend_mutex is locked | |
186 template< typename BackendMutexT, typename BackendT > | |
187 bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) | |
188 { | |
189 #if !defined(BOOST_LOG_NO_THREADS) | |
190 unique_lock< BackendMutexT > lock; | |
191 try | |
192 { | |
193 unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock); | |
194 if (!tmp_lock.owns_lock()) | |
195 return false; | |
196 lock.swap(tmp_lock); | |
197 } | |
198 catch (thread_interrupted&) | |
199 { | |
200 throw; | |
201 } | |
202 catch (...) | |
203 { | |
204 boost::log::aux::shared_lock_guard< mutex_type > frontend_lock(this->frontend_mutex()); | |
205 if (this->exception_handler().empty()) | |
206 throw; | |
207 this->exception_handler()(); | |
208 } | |
209 #endif | |
210 // No need to lock anything in the feed_record method | |
211 boost::log::aux::fake_mutex m; | |
212 feed_record(rec, m, backend); | |
213 return true; | |
214 } | |
215 | |
216 //! Flushes record buffers in the backend, if one supports it | |
217 template< typename BackendMutexT, typename BackendT > | |
218 void flush_backend(BackendMutexT& backend_mutex, BackendT& backend) | |
219 { | |
220 typedef typename BackendT::frontend_requirements frontend_requirements; | |
221 flush_backend_impl(backend_mutex, backend, | |
222 typename has_requirement< frontend_requirements, flushing >::type()); | |
223 } | |
224 | |
225 private: | |
226 //! Flushes record buffers in the backend (the actual implementation) | |
227 template< typename BackendMutexT, typename BackendT > | |
228 void flush_backend_impl(BackendMutexT& backend_mutex, BackendT& backend, mpl::true_) | |
229 { | |
230 try | |
231 { | |
232 BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);) | |
233 backend.flush(); | |
234 } | |
235 #if !defined(BOOST_LOG_NO_THREADS) | |
236 catch (thread_interrupted&) | |
237 { | |
238 throw; | |
239 } | |
240 #endif | |
241 catch (...) | |
242 { | |
243 BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);) | |
244 if (m_ExceptionHandler.empty()) | |
245 throw; | |
246 m_ExceptionHandler(); | |
247 } | |
248 } | |
249 //! Flushes record buffers in the backend (stub for backends that don't support flushing) | |
250 template< typename BackendMutexT, typename BackendT > | |
251 void flush_backend_impl(BackendMutexT&, BackendT&, mpl::false_) | |
252 { | |
253 } | |
254 }; | |
255 | |
256 //! A base class for a logging sink frontend with formatting support | |
257 template< typename CharT > | |
258 class BOOST_LOG_NO_VTABLE basic_formatting_sink_frontend : | |
259 public basic_sink_frontend | |
260 { | |
261 typedef basic_sink_frontend base_type; | |
262 | |
263 public: | |
264 //! Character type | |
265 typedef CharT char_type; | |
266 //! Formatted string type | |
267 typedef std::basic_string< char_type > string_type; | |
268 | |
269 //! Formatter function object type | |
270 typedef basic_formatter< char_type > formatter_type; | |
271 //! Output stream type | |
272 typedef typename formatter_type::stream_type stream_type; | |
273 | |
274 #if !defined(BOOST_LOG_NO_THREADS) | |
275 protected: | |
276 //! Mutex type | |
277 typedef typename base_type::mutex_type mutex_type; | |
278 #endif | |
279 | |
280 private: | |
281 struct formatting_context | |
282 { | |
283 #if !defined(BOOST_LOG_NO_THREADS) | |
284 //! Object version | |
285 const unsigned int m_Version; | |
286 #endif | |
287 //! Formatted log record storage | |
288 string_type m_FormattedRecord; | |
289 //! Formatting stream | |
290 stream_type m_FormattingStream; | |
291 //! Formatter functor | |
292 formatter_type m_Formatter; | |
293 | |
294 formatting_context() : | |
295 #if !defined(BOOST_LOG_NO_THREADS) | |
296 m_Version(0), | |
297 #endif | |
298 m_FormattingStream(m_FormattedRecord) | |
299 { | |
300 m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit); | |
301 } | |
302 #if !defined(BOOST_LOG_NO_THREADS) | |
303 formatting_context(unsigned int version, std::locale const& loc, formatter_type const& formatter) : | |
304 m_Version(version), | |
305 m_FormattingStream(m_FormattedRecord), | |
306 m_Formatter(formatter) | |
307 { | |
308 m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit); | |
309 m_FormattingStream.imbue(loc); | |
310 } | |
311 #endif | |
312 }; | |
313 | |
314 private: | |
315 #if !defined(BOOST_LOG_NO_THREADS) | |
316 | |
317 //! State version | |
318 volatile unsigned int m_Version; | |
319 | |
320 //! Formatter functor | |
321 formatter_type m_Formatter; | |
322 //! Locale to perform formatting | |
323 std::locale m_Locale; | |
324 | |
325 //! Formatting state | |
326 thread_specific_ptr< formatting_context > m_pContext; | |
327 | |
328 #else | |
329 | |
330 //! Formatting state | |
331 formatting_context m_Context; | |
332 | |
333 #endif // !defined(BOOST_LOG_NO_THREADS) | |
334 | |
335 public: | |
336 /*! | |
337 * \brief Initializing constructor | |
338 * | |
339 * \param cross_thread The flag indicates whether the sink passes log records between different threads | |
340 */ | |
341 explicit basic_formatting_sink_frontend(bool cross_thread) : | |
342 basic_sink_frontend(cross_thread) | |
343 #if !defined(BOOST_LOG_NO_THREADS) | |
344 , m_Version(0) | |
345 #endif | |
346 { | |
347 } | |
348 | |
349 /*! | |
350 * The method sets sink-specific formatter function object | |
351 */ | |
352 template< typename FunT > | |
353 void set_formatter(FunT const& formatter) | |
354 { | |
355 #if !defined(BOOST_LOG_NO_THREADS) | |
356 boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex()); | |
357 m_Formatter = formatter; | |
358 ++m_Version; | |
359 #else | |
360 m_Context.m_Formatter = formatter; | |
361 #endif | |
362 } | |
363 /*! | |
364 * The method resets the formatter | |
365 */ | |
366 void reset_formatter() | |
367 { | |
368 #if !defined(BOOST_LOG_NO_THREADS) | |
369 boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex()); | |
370 m_Formatter.reset(); | |
371 ++m_Version; | |
372 #else | |
373 m_Context.m_Formatter.reset(); | |
374 #endif | |
375 } | |
376 | |
377 /*! | |
378 * The method returns the current locale used for formatting | |
379 */ | |
380 std::locale getloc() const | |
381 { | |
382 #if !defined(BOOST_LOG_NO_THREADS) | |
383 boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex()); | |
384 return m_Locale; | |
385 #else | |
386 return m_Context.m_FormattingStream.getloc(); | |
387 #endif | |
388 } | |
389 /*! | |
390 * The method sets the locale used for formatting | |
391 */ | |
392 void imbue(std::locale const& loc) | |
393 { | |
394 #if !defined(BOOST_LOG_NO_THREADS) | |
395 boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex()); | |
396 m_Locale = loc; | |
397 ++m_Version; | |
398 #else | |
399 m_Context.m_FormattingStream.imbue(loc); | |
400 #endif | |
401 } | |
402 | |
403 protected: | |
404 //! Returns reference to the formatter | |
405 formatter_type& formatter() | |
406 { | |
407 #if !defined(BOOST_LOG_NO_THREADS) | |
408 return m_Formatter; | |
409 #else | |
410 return m_Context.m_Formatter; | |
411 #endif | |
412 } | |
413 | |
414 //! Feeds log record to the backend | |
415 template< typename BackendMutexT, typename BackendT > | |
416 void feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) | |
417 { | |
418 formatting_context* context; | |
419 | |
420 #if !defined(BOOST_LOG_NO_THREADS) | |
421 context = m_pContext.get(); | |
422 if (!context || context->m_Version != m_Version) | |
423 { | |
424 { | |
425 boost::log::aux::shared_lock_guard< mutex_type > lock(this->frontend_mutex()); | |
426 context = new formatting_context(m_Version, m_Locale, m_Formatter); | |
427 } | |
428 m_pContext.reset(context); | |
429 } | |
430 #else | |
431 context = &m_Context; | |
432 #endif | |
433 | |
434 boost::log::aux::cleanup_guard< stream_type > cleanup1(context->m_FormattingStream); | |
435 boost::log::aux::cleanup_guard< string_type > cleanup2(context->m_FormattedRecord); | |
436 | |
437 try | |
438 { | |
439 // Perform the formatting | |
440 context->m_Formatter(rec, context->m_FormattingStream); | |
441 context->m_FormattingStream.flush(); | |
442 | |
443 // Feed the record | |
444 BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);) | |
445 backend.consume(rec, context->m_FormattedRecord); | |
446 } | |
447 #if !defined(BOOST_LOG_NO_THREADS) | |
448 catch (thread_interrupted&) | |
449 { | |
450 throw; | |
451 } | |
452 #endif | |
453 catch (...) | |
454 { | |
455 BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(this->frontend_mutex());) | |
456 if (this->exception_handler().empty()) | |
457 throw; | |
458 this->exception_handler()(); | |
459 } | |
460 } | |
461 | |
462 //! Attempts to feeds log record to the backend, does not block if \a backend_mutex is locked | |
463 template< typename BackendMutexT, typename BackendT > | |
464 bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend) | |
465 { | |
466 #if !defined(BOOST_LOG_NO_THREADS) | |
467 unique_lock< BackendMutexT > lock; | |
468 try | |
469 { | |
470 unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock); | |
471 if (!tmp_lock.owns_lock()) | |
472 return false; | |
473 lock.swap(tmp_lock); | |
474 } | |
475 catch (thread_interrupted&) | |
476 { | |
477 throw; | |
478 } | |
479 catch (...) | |
480 { | |
481 boost::log::aux::shared_lock_guard< mutex_type > frontend_lock(this->frontend_mutex()); | |
482 if (this->exception_handler().empty()) | |
483 throw; | |
484 this->exception_handler()(); | |
485 } | |
486 #endif | |
487 // No need to lock anything in the feed_record method | |
488 boost::log::aux::fake_mutex m; | |
489 feed_record(rec, m, backend); | |
490 return true; | |
491 } | |
492 }; | |
493 | |
494 namespace aux { | |
495 | |
496 template< | |
497 typename BackendT, | |
498 bool RequiresFormattingV = has_requirement< | |
499 typename BackendT::frontend_requirements, | |
500 formatted_records | |
501 >::value | |
502 > | |
503 struct make_sink_frontend_base | |
504 { | |
505 typedef basic_sink_frontend type; | |
506 }; | |
507 template< typename BackendT > | |
508 struct make_sink_frontend_base< BackendT, true > | |
509 { | |
510 typedef basic_formatting_sink_frontend< typename BackendT::char_type > type; | |
511 }; | |
512 | |
513 } // namespace aux | |
514 | |
515 } // namespace sinks | |
516 | |
517 BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
518 | |
519 } // namespace boost | |
520 | |
521 #include <boost/log/detail/footer.hpp> | |
522 | |
523 #endif // BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_ |