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