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 record_ostream.cpp |
9 | * \author Andrey Semashev |
10 | * \date 17.04.2008 |
11 | * |
12 | * \brief This header is the Boost.Log library implementation, see the library documentation |
13 | * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. |
14 | */ |
15 | |
16 | #include <boost/log/detail/config.hpp> |
17 | #include <locale> |
18 | #include <utility> |
19 | #include <boost/log/sources/record_ostream.hpp> |
20 | #include <boost/log/detail/singleton.hpp> |
21 | #include <boost/log/attributes/attribute_value_impl.hpp> |
22 | #include <boost/log/expressions/message.hpp> |
23 | #if !defined(BOOST_LOG_NO_THREADS) |
24 | #include <boost/thread/tss.hpp> |
25 | #endif |
26 | #include "unique_ptr.hpp" |
27 | #include <boost/log/detail/header.hpp> |
28 | |
29 | namespace boost { |
30 | |
31 | BOOST_LOG_OPEN_NAMESPACE |
32 | |
33 | //! The function initializes the stream and the stream buffer |
34 | template< typename CharT > |
35 | BOOST_LOG_API void basic_record_ostream< CharT >::init_stream() |
36 | { |
37 | base_type::init_stream(); |
38 | base_type::imbue(std::locale()); |
39 | if (m_record) |
40 | { |
41 | typedef attributes::attribute_value_impl< string_type > message_impl_type; |
42 | intrusive_ptr< message_impl_type > p = new message_impl_type(string_type()); |
43 | attribute_value value(p); |
44 | |
45 | // This may fail if the record already has Message attribute |
46 | std::pair< attribute_value_set::const_iterator, bool > res = |
47 | m_record->attribute_values().insert(key: expressions::tag::message::get_name(), mapped: value); |
48 | if (!res.second) |
49 | const_cast< attribute_value& >(res.first->second).swap(that&: value); |
50 | |
51 | base_type::attach(const_cast< string_type& >(p->get())); |
52 | } |
53 | } |
54 | //! The function resets the stream into a detached (default initialized) state |
55 | template< typename CharT > |
56 | BOOST_LOG_API void basic_record_ostream< CharT >::detach_from_record() BOOST_NOEXCEPT |
57 | { |
58 | if (m_record) |
59 | { |
60 | base_type::detach(); |
61 | m_record = NULL; |
62 | base_type::exceptions(base_type::goodbit); |
63 | } |
64 | } |
65 | |
66 | namespace aux { |
67 | |
68 | BOOST_LOG_ANONYMOUS_NAMESPACE { |
69 | |
70 | //! The pool of stream compounds |
71 | template< typename CharT > |
72 | class stream_compound_pool : |
73 | public log::aux::lazy_singleton< |
74 | stream_compound_pool< CharT >, |
75 | #if !defined(BOOST_LOG_NO_THREADS) |
76 | thread_specific_ptr< stream_compound_pool< CharT > > |
77 | #else |
78 | log::aux::unique_ptr< stream_compound_pool< CharT > > |
79 | #endif |
80 | > |
81 | { |
82 | //! Self type |
83 | typedef stream_compound_pool< CharT > this_type; |
84 | #if !defined(BOOST_LOG_NO_THREADS) |
85 | //! Thread-specific pointer type |
86 | typedef thread_specific_ptr< this_type > tls_ptr_type; |
87 | #else |
88 | //! Thread-specific pointer type |
89 | typedef log::aux::unique_ptr< this_type > tls_ptr_type; |
90 | #endif |
91 | //! Singleton base type |
92 | typedef log::aux::lazy_singleton< |
93 | this_type, |
94 | tls_ptr_type |
95 | > base_type; |
96 | //! Stream compound type |
97 | typedef typename stream_provider< CharT >::stream_compound stream_compound_t; |
98 | |
99 | public: |
100 | //! Pooled stream compounds |
101 | stream_compound_t* m_Top; |
102 | |
103 | ~stream_compound_pool() |
104 | { |
105 | stream_compound_t* p = NULL; |
106 | while ((p = m_Top) != NULL) |
107 | { |
108 | m_Top = p->next; |
109 | delete p; |
110 | } |
111 | } |
112 | |
113 | //! The method returns pool instance |
114 | static stream_compound_pool& get() |
115 | { |
116 | tls_ptr_type& ptr = base_type::get(); |
117 | this_type* p = ptr.get(); |
118 | if (!p) |
119 | { |
120 | log::aux::unique_ptr< this_type > pNew(new this_type()); |
121 | ptr.reset(pNew.get()); |
122 | p = pNew.release(); |
123 | } |
124 | return *p; |
125 | } |
126 | |
127 | private: |
128 | stream_compound_pool() : m_Top(NULL) {} |
129 | }; |
130 | |
131 | } // namespace |
132 | |
133 | //! The method returns an allocated stream compound |
134 | template< typename CharT > |
135 | BOOST_LOG_API typename stream_provider< CharT >::stream_compound* |
136 | stream_provider< CharT >::allocate_compound(record& rec) |
137 | { |
138 | stream_compound_pool< char_type >& pool = stream_compound_pool< char_type >::get(); |
139 | if (pool.m_Top) |
140 | { |
141 | stream_compound* p = pool.m_Top; |
142 | pool.m_Top = p->next; |
143 | p->next = NULL; |
144 | p->stream.attach_record(rec); |
145 | return p; |
146 | } |
147 | else |
148 | return new stream_compound(rec); |
149 | } |
150 | |
151 | //! The method releases a compound |
152 | template< typename CharT > |
153 | BOOST_LOG_API void stream_provider< CharT >::release_compound(stream_compound* compound) BOOST_NOEXCEPT |
154 | { |
155 | stream_compound_pool< char_type >& pool = stream_compound_pool< char_type >::get(); |
156 | compound->next = pool.m_Top; |
157 | pool.m_Top = compound; |
158 | compound->stream.detach_from_record(); |
159 | } |
160 | |
161 | //! Explicitly instantiate stream_provider implementation |
162 | #ifdef BOOST_LOG_USE_CHAR |
163 | template struct stream_provider< char >; |
164 | #endif |
165 | #ifdef BOOST_LOG_USE_WCHAR_T |
166 | template struct stream_provider< wchar_t >; |
167 | #endif |
168 | |
169 | } // namespace aux |
170 | |
171 | //! Explicitly instantiate basic_record_ostream implementation |
172 | #ifdef BOOST_LOG_USE_CHAR |
173 | template class basic_record_ostream< char >; |
174 | #endif |
175 | #ifdef BOOST_LOG_USE_WCHAR_T |
176 | template class basic_record_ostream< wchar_t >; |
177 | #endif |
178 | |
179 | BOOST_LOG_CLOSE_NAMESPACE // namespace log |
180 | |
181 | } // namespace boost |
182 | |
183 | #include <boost/log/detail/footer.hpp> |
184 |