summaryrefslogtreecommitdiff
path: root/libs/log/src/record_ostream.cpp
blob: 5d9e95f96cc8a8bbab9a6d6d28b9de8036daf824 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 *          Copyright Andrey Semashev 2007 - 2014.
 * 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>