]>
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 sync_frontend.hpp | |
9 | * \author Andrey Semashev | |
10 | * \date 14.07.2009 | |
11 | * | |
12 | * The header contains implementation of synchronous sink frontend. | |
13 | */ | |
14 | ||
15 | #ifndef BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_ | |
16 | #define BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_ | |
17 | ||
18 | #include <boost/log/detail/config.hpp> | |
19 | ||
20 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
21 | #pragma once | |
22 | #endif | |
23 | ||
24 | #if defined(BOOST_LOG_NO_THREADS) | |
25 | #error Boost.Log: Synchronous sink frontend is only supported in multithreaded environment | |
26 | #endif | |
27 | ||
28 | #include <boost/static_assert.hpp> | |
29 | #include <boost/smart_ptr/shared_ptr.hpp> | |
30 | #include <boost/smart_ptr/make_shared_object.hpp> | |
31 | #include <boost/preprocessor/control/if.hpp> | |
32 | #include <boost/preprocessor/comparison/equal.hpp> | |
33 | #include <boost/thread/recursive_mutex.hpp> | |
34 | #include <boost/log/detail/locking_ptr.hpp> | |
35 | #include <boost/log/detail/parameter_tools.hpp> | |
36 | #include <boost/log/core/record_view.hpp> | |
37 | #include <boost/log/sinks/basic_sink_frontend.hpp> | |
38 | #include <boost/log/sinks/frontend_requirements.hpp> | |
39 | #include <boost/log/detail/header.hpp> | |
40 | ||
41 | namespace boost { | |
42 | ||
43 | BOOST_LOG_OPEN_NAMESPACE | |
44 | ||
45 | namespace sinks { | |
46 | ||
47 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
48 | ||
49 | #define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1(n, data)\ | |
50 | template< typename T0 >\ | |
51 | explicit synchronous_sink(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\ | |
52 | base_type(false),\ | |
53 | m_pBackend(boost::make_shared< sink_backend_type >(arg0)) {} | |
54 | ||
55 | #define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N(n, data)\ | |
56 | template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ | |
57 | explicit synchronous_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\ | |
58 | base_type(false),\ | |
59 | m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))) {} | |
60 | ||
61 | #define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, data)\ | |
62 | BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1, BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N)(n, data) | |
63 | ||
64 | #endif // BOOST_LOG_DOXYGEN_PASS | |
65 | ||
66 | /*! | |
67 | * \brief Synchronous logging sink frontend | |
68 | * | |
69 | * The sink frontend serializes threads before passing logging records to the backend | |
70 | */ | |
71 | template< typename SinkBackendT > | |
72 | class synchronous_sink : | |
73 | public aux::make_sink_frontend_base< SinkBackendT >::type | |
74 | { | |
75 | typedef typename aux::make_sink_frontend_base< SinkBackendT >::type base_type; | |
76 | ||
77 | private: | |
78 | //! Synchronization mutex type | |
79 | typedef boost::recursive_mutex backend_mutex_type; | |
80 | ||
81 | public: | |
82 | //! Sink implementation type | |
83 | typedef SinkBackendT sink_backend_type; | |
84 | //! \cond | |
85 | BOOST_STATIC_ASSERT_MSG((has_requirement< typename sink_backend_type::frontend_requirements, synchronized_feeding >::value), "Synchronous sink frontend is incompatible with the specified backend: thread synchronization requirements are not met"); | |
86 | //! \endcond | |
87 | ||
88 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
89 | ||
90 | //! A pointer type that locks the backend until it's destroyed | |
91 | typedef boost::log::aux::locking_ptr< sink_backend_type, backend_mutex_type > locked_backend_ptr; | |
92 | ||
93 | #else // BOOST_LOG_DOXYGEN_PASS | |
94 | ||
95 | //! A pointer type that locks the backend until it's destroyed | |
96 | typedef implementation_defined locked_backend_ptr; | |
97 | ||
98 | #endif // BOOST_LOG_DOXYGEN_PASS | |
99 | ||
100 | private: | |
101 | //! Synchronization mutex | |
102 | backend_mutex_type m_BackendMutex; | |
103 | //! Pointer to the backend | |
104 | const shared_ptr< sink_backend_type > m_pBackend; | |
105 | ||
106 | public: | |
107 | /*! | |
108 | * Default constructor. Constructs the sink backend instance. | |
109 | * Requires the backend to be default-constructible. | |
110 | */ | |
111 | synchronous_sink() : | |
112 | base_type(false), | |
113 | m_pBackend(boost::make_shared< sink_backend_type >()) | |
114 | { | |
115 | } | |
116 | /*! | |
117 | * Constructor attaches user-constructed backend instance | |
118 | * | |
119 | * \param backend Pointer to the backend instance | |
120 | * | |
121 | * \pre \a backend is not \c NULL. | |
122 | */ | |
123 | explicit synchronous_sink(shared_ptr< sink_backend_type > const& backend) : | |
124 | base_type(false), | |
125 | m_pBackend(backend) | |
126 | { | |
127 | } | |
128 | ||
129 | /*! | |
130 | * Constructor that passes arbitrary named parameters to the interprocess sink backend constructor. | |
131 | * Refer to the backend documentation for the list of supported parameters. | |
132 | */ | |
133 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
134 | BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~) | |
135 | #else | |
136 | template< typename... Args > | |
137 | explicit synchronous_sink(Args&&... args); | |
138 | #endif | |
139 | ||
140 | /*! | |
141 | * Locking accessor to the attached backend | |
142 | */ | |
143 | locked_backend_ptr locked_backend() | |
144 | { | |
145 | return locked_backend_ptr(m_pBackend, m_BackendMutex); | |
146 | } | |
147 | ||
148 | /*! | |
149 | * Passes the log record to the backend | |
150 | */ | |
151 | void consume(record_view const& rec) | |
152 | { | |
153 | base_type::feed_record(rec, m_BackendMutex, *m_pBackend); | |
154 | } | |
155 | ||
156 | /*! | |
157 | * The method attempts to pass logging record to the backend | |
158 | */ | |
159 | bool try_consume(record_view const& rec) | |
160 | { | |
161 | return base_type::try_feed_record(rec, m_BackendMutex, *m_pBackend); | |
162 | } | |
163 | ||
164 | /*! | |
165 | * The method performs flushing of any internal buffers that may hold log records. The method | |
166 | * may take considerable time to complete and may block both the calling thread and threads | |
167 | * attempting to put new records into the sink while this call is in progress. | |
168 | */ | |
169 | void flush() | |
170 | { | |
171 | base_type::flush_backend(m_BackendMutex, *m_pBackend); | |
172 | } | |
173 | }; | |
174 | ||
175 | #undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1 | |
176 | #undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N | |
177 | #undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL | |
178 | ||
179 | } // namespace sinks | |
180 | ||
181 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
182 | ||
183 | } // namespace boost | |
184 | ||
185 | #include <boost/log/detail/footer.hpp> | |
186 | ||
187 | #endif // BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_ |