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
29namespace boost {
30
31BOOST_LOG_OPEN_NAMESPACE
32
33//! The function initializes the stream and the stream buffer
34template< typename CharT >
35BOOST_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
55template< typename CharT >
56BOOST_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
66namespace aux {
67
68BOOST_LOG_ANONYMOUS_NAMESPACE {
69
70//! The pool of stream compounds
71template< typename CharT >
72class 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
99public:
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
127private:
128 stream_compound_pool() : m_Top(NULL) {}
129};
130
131} // namespace
132
133//! The method returns an allocated stream compound
134template< typename CharT >
135BOOST_LOG_API typename stream_provider< CharT >::stream_compound*
136stream_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
152template< typename CharT >
153BOOST_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
163template struct stream_provider< char >;
164#endif
165#ifdef BOOST_LOG_USE_WCHAR_T
166template 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
173template class basic_record_ostream< char >;
174#endif
175#ifdef BOOST_LOG_USE_WCHAR_T
176template class basic_record_ostream< wchar_t >;
177#endif
178
179BOOST_LOG_CLOSE_NAMESPACE // namespace log
180
181} // namespace boost
182
183#include <boost/log/detail/footer.hpp>
184

source code of boost/libs/log/src/record_ostream.cpp