]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Copyright Lingxi Li 2015. | |
3 | * Copyright Andrey Semashev 2016. | |
4 | * Distributed under the Boost Software License, Version 1.0. | |
5 | * (See accompanying file LICENSE_1_0.txt or copy at | |
6 | * http://www.boost.org/LICENSE_1_0.txt) | |
7 | */ | |
8 | /*! | |
9 | * \file text_ipc_message_queue_backend.hpp | |
10 | * \author Lingxi Li | |
11 | * \author Andrey Semashev | |
12 | * \date 14.10.2015 | |
13 | * | |
14 | * The header contains implementation of a text interprocess message queue sink | |
15 | * backend along with implementation of a supporting interprocess message queue. | |
16 | */ | |
17 | ||
18 | #ifndef BOOST_LOG_SINKS_TEXT_IPC_MESSAGE_QUEUE_BACKEND_HPP_INCLUDED_ | |
19 | #define BOOST_LOG_SINKS_TEXT_IPC_MESSAGE_QUEUE_BACKEND_HPP_INCLUDED_ | |
20 | ||
21 | #include <limits> | |
22 | #include <string> | |
23 | #include <boost/cstdint.hpp> | |
24 | #include <boost/move/core.hpp> | |
25 | #include <boost/preprocessor/control/if.hpp> | |
26 | #include <boost/preprocessor/comparison/equal.hpp> | |
27 | #include <boost/log/detail/config.hpp> | |
28 | #include <boost/log/detail/parameter_tools.hpp> | |
29 | #include <boost/log/core/record_view.hpp> | |
30 | #include <boost/log/sinks/basic_sink_backend.hpp> | |
31 | #include <boost/log/sinks/frontend_requirements.hpp> | |
32 | #include <boost/log/exceptions.hpp> | |
33 | #include <boost/log/detail/header.hpp> | |
34 | ||
35 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
36 | #pragma once | |
37 | #endif | |
38 | ||
39 | namespace boost { | |
40 | ||
41 | BOOST_LOG_OPEN_NAMESPACE | |
42 | ||
43 | namespace sinks { | |
44 | ||
45 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
46 | ||
47 | #define BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_1(n, data)\ | |
48 | template< typename T0 >\ | |
49 | explicit text_ipc_message_queue_backend(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\ | |
50 | m_queue(arg0) {} | |
51 | ||
52 | #define BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_N(n, data)\ | |
53 | template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ | |
54 | explicit text_ipc_message_queue_backend(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\ | |
55 | m_queue(BOOST_PP_ENUM_PARAMS(n, arg)) {} | |
56 | ||
57 | #define BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL(z, n, data)\ | |
58 | BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_1, BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_N)(n, data) | |
59 | ||
60 | #endif // BOOST_LOG_DOXYGEN_PASS | |
61 | ||
62 | /*! | |
63 | * \brief An implementation of a text interprocess message queue sink backend and | |
64 | * a supporting interprocess message queue. | |
65 | * | |
66 | * The sink backend sends formatted log messages to an interprocess message queue | |
67 | * which can be extracted by a viewer process. Methods of this class are not | |
68 | * thread-safe, unless otherwise specified. | |
69 | */ | |
70 | template< typename QueueT > | |
71 | class text_ipc_message_queue_backend : | |
72 | public basic_formatted_sink_backend< char, concurrent_feeding > | |
73 | { | |
74 | //! Base type | |
75 | typedef basic_formatted_sink_backend< char, concurrent_feeding > base_type; | |
76 | ||
77 | public: | |
78 | //! Character type | |
79 | typedef base_type::char_type char_type; | |
80 | //! String type to be used as a message text holder | |
81 | typedef base_type::string_type string_type; | |
82 | //! Interprocess message queue type | |
83 | typedef QueueT queue_type; | |
84 | ||
85 | private: | |
86 | //! Interprocess queue | |
87 | queue_type m_queue; | |
88 | ||
89 | public: | |
90 | /*! | |
91 | * Default constructor. The method constructs the backend using the default-constructed | |
92 | * interprocess message queue. The queue may need additional setup in order to be able | |
93 | * to send messages. | |
94 | */ | |
95 | text_ipc_message_queue_backend() BOOST_NOEXCEPT | |
96 | { | |
97 | } | |
98 | ||
99 | /*! | |
100 | * Initializing constructor. The method constructs the backend using the provided | |
101 | * interprocess message queue. The constructor moves from the provided queue. | |
102 | */ | |
103 | explicit text_ipc_message_queue_backend(BOOST_RV_REF(queue_type) queue) BOOST_NOEXCEPT : | |
104 | m_queue(static_cast< BOOST_RV_REF(queue_type) >(queue)) | |
105 | { | |
106 | } | |
107 | ||
108 | /*! | |
109 | * Constructor that passes arbitrary named parameters to the interprocess queue constructor. | |
110 | * Refer to the queue documentation for the list of supported parameters. | |
111 | */ | |
112 | #ifndef BOOST_LOG_DOXYGEN_PASS | |
113 | BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL, ~) | |
114 | #else | |
115 | template< typename... Args > | |
116 | explicit text_ipc_message_queue_backend(Args&&... args); | |
117 | #endif | |
118 | ||
119 | /*! | |
120 | * The method returns a reference to the managed \c queue_type object. | |
121 | * | |
122 | * \return A reference to the managed \c queue_type object. | |
123 | */ | |
124 | queue_type& message_queue() BOOST_NOEXCEPT { return m_queue; } | |
125 | ||
126 | /*! | |
127 | * The method returns a constant reference to the managed \c queue_type object. | |
128 | * | |
129 | * \return A constant reference to the managed \c queue_type object. | |
130 | */ | |
131 | queue_type const& message_queue() const BOOST_NOEXCEPT { return m_queue; } | |
132 | ||
133 | /*! | |
134 | * Tests whether the object is associated with any message queue. Only when the backend has | |
135 | * an associated message queue, will any message be sent. | |
136 | * | |
137 | * \return \c true if the object is associated with a message queue, and \c false otherwise. | |
138 | */ | |
139 | bool is_open() const BOOST_NOEXCEPT { return m_queue.is_open(); } | |
140 | ||
141 | /*! | |
142 | * The method writes the message to the backend. Concurrent calls to this method | |
143 | * are allowed. Therefore, the backend may be used with unlocked frontend. <tt>stop_local()</tt> | |
144 | * can be used to have a blocked <tt>consume()</tt> call return and prevent future | |
145 | * calls to <tt>consume()</tt> from blocking. | |
146 | */ | |
147 | void consume(record_view const&, string_type const& formatted_message) | |
148 | { | |
149 | if (m_queue.is_open()) | |
150 | { | |
151 | typedef typename queue_type::size_type size_type; | |
152 | const string_type::size_type size = formatted_message.size(); | |
153 | if (BOOST_UNLIKELY(size > static_cast< string_type::size_type >((std::numeric_limits< size_type >::max)()))) | |
154 | BOOST_LOG_THROW_DESCR(limitation_error, "Message too long to send to an interprocess queue"); | |
155 | m_queue.send(formatted_message.data(), static_cast< size_type >(size)); | |
156 | } | |
157 | } | |
158 | }; | |
159 | ||
160 | #undef BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_1 | |
161 | #undef BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_N | |
162 | #undef BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL | |
163 | ||
164 | } // namespace sinks | |
165 | ||
166 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
167 | ||
168 | } // namespace boost | |
169 | ||
170 | #include <boost/log/detail/footer.hpp> | |
171 | ||
172 | #endif // BOOST_LOG_SINKS_TEXT_IPC_MESSAGE_QUEUE_BACKEND_HPP_INCLUDED_ |