blob: 7eb3b71da8883b866b430a5bc203d58bede4b6bc [file] [log] [blame]
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file record_ostream.cpp
* \author Andrey Semashev
* \date 17.04.2008
*
* \brief This header is the Boost.Log library implementation, see the library documentation
* at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
*/
#include <memory>
#include <locale>
#include <boost/log/sources/record_ostream.hpp>
#include <boost/log/detail/singleton.hpp>
#include <boost/log/attributes/attribute_value_impl.hpp>
#include <boost/log/expressions/message.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/thread/tss.hpp>
#endif
#include <boost/log/detail/header.hpp>
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
//! The function initializes the stream and the stream buffer
template< typename CharT >
BOOST_LOG_API void basic_record_ostream< CharT >::init_stream()
{
base_type::imbue(std::locale());
if (m_record)
{
typedef attributes::attribute_value_impl< string_type > message_impl_type;
intrusive_ptr< message_impl_type > p = new message_impl_type(string_type());
attribute_value value(p);
// This may fail if the record already has Message attribute
std::pair< attribute_value_set::const_iterator, bool > res =
m_record->attribute_values().insert(expressions::tag::message::get_name(), value);
if (!res.second)
const_cast< attribute_value& >(res.first->second).swap(value);
base_type::attach(const_cast< string_type& >(p->get()));
}
}
//! The function resets the stream into a detached (default initialized) state
template< typename CharT >
BOOST_LOG_API void basic_record_ostream< CharT >::detach_from_record() BOOST_NOEXCEPT
{
if (m_record)
{
base_type::detach();
m_record = NULL;
base_type::exceptions(stream_type::goodbit);
}
}
namespace aux {
BOOST_LOG_ANONYMOUS_NAMESPACE {
//! The pool of stream compounds
template< typename CharT >
class stream_compound_pool :
public log::aux::lazy_singleton<
stream_compound_pool< CharT >,
#if !defined(BOOST_LOG_NO_THREADS)
thread_specific_ptr< stream_compound_pool< CharT > >
#else
std::auto_ptr< stream_compound_pool< CharT > >
#endif
>
{
//! Self type
typedef stream_compound_pool< CharT > this_type;
#if !defined(BOOST_LOG_NO_THREADS)
//! Thread-specific pointer type
typedef thread_specific_ptr< this_type > tls_ptr_type;
#else
//! Thread-specific pointer type
typedef std::auto_ptr< this_type > tls_ptr_type;
#endif
//! Singleton base type
typedef log::aux::lazy_singleton<
this_type,
tls_ptr_type
> base_type;
//! Stream compound type
typedef typename stream_provider< CharT >::stream_compound stream_compound_t;
public:
//! Pooled stream compounds
stream_compound_t* m_Top;
~stream_compound_pool()
{
stream_compound_t* p = NULL;
while ((p = m_Top) != NULL)
{
m_Top = p->next;
delete p;
}
}
//! The method returns pool instance
static stream_compound_pool& get()
{
tls_ptr_type& ptr = base_type::get();
this_type* p = ptr.get();
if (!p)
{
std::auto_ptr< this_type > pNew(new this_type());
ptr.reset(pNew.get());
p = pNew.release();
}
return *p;
}
private:
stream_compound_pool() : m_Top(NULL) {}
};
} // namespace
//! The method returns an allocated stream compound
template< typename CharT >
BOOST_LOG_API typename stream_provider< CharT >::stream_compound*
stream_provider< CharT >::allocate_compound(record& rec)
{
stream_compound_pool< char_type >& pool = stream_compound_pool< char_type >::get();
if (pool.m_Top)
{
stream_compound* p = pool.m_Top;
pool.m_Top = p->next;
p->next = NULL;
p->stream.attach_record(rec);
return p;
}
else
return new stream_compound(rec);
}
//! The method releases a compound
template< typename CharT >
BOOST_LOG_API void stream_provider< CharT >::release_compound(stream_compound* compound) BOOST_NOEXCEPT
{
stream_compound_pool< char_type >& pool = stream_compound_pool< char_type >::get();
compound->next = pool.m_Top;
pool.m_Top = compound;
compound->stream.detach_from_record();
}
//! Explicitly instantiate stream_provider implementation
#ifdef BOOST_LOG_USE_CHAR
template struct stream_provider< char >;
#endif
#ifdef BOOST_LOG_USE_WCHAR_T
template struct stream_provider< wchar_t >;
#endif
} // namespace aux
//! Explicitly instantiate basic_record_ostream implementation
#ifdef BOOST_LOG_USE_CHAR
template class basic_record_ostream< char >;
#endif
#ifdef BOOST_LOG_USE_WCHAR_T
template class basic_record_ostream< wchar_t >;
#endif
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>