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)
8 * \file attribute_name.cpp
9 * \author Andrey Semashev
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.
16 #include <boost/log/detail/config.hpp>
21 #include <boost/assert.hpp>
22 #include <boost/throw_exception.hpp>
23 #include <boost/smart_ptr/shared_ptr.hpp>
24 #include <boost/smart_ptr/make_shared_object.hpp>
25 #include <boost/intrusive/set.hpp>
26 #include <boost/intrusive/set_hook.hpp>
27 #include <boost/intrusive/options.hpp>
28 #include <boost/log/exceptions.hpp>
29 #include <boost/log/detail/singleton.hpp>
30 #include <boost/log/attributes/attribute_name.hpp>
31 #if !defined(BOOST_LOG_NO_THREADS)
32 #include <boost/log/detail/locks.hpp>
33 #include <boost/log/detail/light_rw_mutex.hpp>
35 #include <boost/log/detail/header.hpp>
39 BOOST_LOG_OPEN_NAMESPACE
41 //! A global container of all known attribute names
42 class attribute_name::repository
:
43 public log::aux::lazy_singleton
<
45 shared_ptr
< repository
>
48 typedef log::aux::lazy_singleton
<
50 shared_ptr
< repository
>
53 #if !defined(BOOST_LOG_BROKEN_FRIEND_TEMPLATE_SPECIALIZATIONS)
54 friend class log::aux::lazy_singleton
<
56 shared_ptr
< repository
>
59 friend class base_type
;
63 // Import types from the basic_attribute_name template
64 typedef attribute_name::id_type id_type
;
65 typedef attribute_name::string_type string_type
;
67 //! A base hook for arranging the attribute names into a set
68 typedef intrusive::set_base_hook
<
69 intrusive::link_mode
< intrusive::safe_link
>,
70 intrusive::optimize_size
< true >
74 //! An element of the attribute names repository
76 public node_by_name_hook
78 typedef node_by_name_hook base_type
;
81 //! A predicate for name-based ordering
84 typedef bool result_type
;
86 bool operator() (node
const& left
, node
const& right
) const
88 return std::strcmp(left
.m_name
.c_str(), right
.m_name
.c_str()) < 0;
90 bool operator() (node
const& left
, const char* right
) const
92 return std::strcmp(left
.m_name
.c_str(), right
) < 0;
94 bool operator() (const char* left
, node
const& right
) const
96 return std::strcmp(left
, right
.m_name
.c_str()) < 0;
105 node() : m_id(0), m_name() {}
106 node(id_type i
, string_type
const& n
) :
112 node(node
const& that
) :
120 //! The container that provides storage for nodes
121 typedef std::deque
< node
> node_list
;
122 //! The container that provides name-based lookup
123 typedef intrusive::set
<
125 intrusive::base_hook
< node_by_name_hook
>,
126 intrusive::constant_time_size
< false >,
127 intrusive::compare
< node::order_by_name
>
131 #if !defined(BOOST_LOG_NO_THREADS)
132 typedef log::aux::light_rw_mutex mutex_type
;
133 log::aux::light_rw_mutex m_Mutex
;
135 node_list m_NodeList
;
139 //! Converts attribute name string to id
140 id_type
get_id_from_string(const char* name
)
142 BOOST_ASSERT(name
!= NULL
);
144 #if !defined(BOOST_LOG_NO_THREADS)
146 // Do a non-blocking lookup first
147 log::aux::shared_lock_guard
< mutex_type
> _(m_Mutex
);
148 node_set::const_iterator it
=
149 m_NodeSet
.find(name
, node::order_by_name());
150 if (it
!= m_NodeSet
.end())
153 #endif // !defined(BOOST_LOG_NO_THREADS)
155 BOOST_LOG_EXPR_IF_MT(log::aux::exclusive_lock_guard
< mutex_type
> _(m_Mutex
);)
156 node_set::iterator it
=
157 m_NodeSet
.lower_bound(name
, node::order_by_name());
158 if (it
== m_NodeSet
.end() || it
->m_name
!= name
)
160 const std::size_t new_id
= m_NodeList
.size();
161 if (new_id
>= static_cast< id_type
>(attribute_name::uninitialized
))
162 BOOST_THROW_EXCEPTION(limitation_error("Too many log attribute names"));
164 m_NodeList
.push_back(node(static_cast< id_type
>(new_id
), name
));
165 it
= m_NodeSet
.insert(it
, m_NodeList
.back());
170 //! Converts id to the attribute name string
171 string_type
const& get_string_from_id(id_type id
)
173 BOOST_LOG_EXPR_IF_MT(log::aux::shared_lock_guard
< mutex_type
> _(m_Mutex
);)
174 BOOST_ASSERT(id
< m_NodeList
.size());
175 return m_NodeList
[id
].m_name
;
179 //! Initializes the singleton instance
180 static void init_instance()
182 base_type::get_instance() = boost::make_shared
< repository
>();
186 BOOST_LOG_API
attribute_name::id_type
187 attribute_name::get_id_from_string(const char* name
)
189 return repository::get()->get_id_from_string(name
);
192 BOOST_LOG_API
attribute_name::string_type
const&
193 attribute_name::get_string_from_id(id_type id
)
195 return repository::get()->get_string_from_id(id
);
198 template< typename CharT
, typename TraitsT
>
199 BOOST_LOG_API
std::basic_ostream
< CharT
, TraitsT
>& operator<< (
200 std::basic_ostream
< CharT
, TraitsT
>& strm
,
201 attribute_name
const& name
)
204 strm
<< name
.string().c_str();
206 strm
<< "[uninitialized]";
210 // Explicitly instantiate attribute name implementation
211 #ifdef BOOST_LOG_USE_CHAR
212 template BOOST_LOG_API
std::basic_ostream
< char, std::char_traits
< char > >&
213 operator<< < char, std::char_traits
< char > >(
214 std::basic_ostream
< char, std::char_traits
< char > >& strm
,
215 attribute_name
const& name
);
217 #ifdef BOOST_LOG_USE_WCHAR_T
218 template BOOST_LOG_API
std::basic_ostream
< wchar_t, std::char_traits
< wchar_t > >&
219 operator<< < wchar_t, std::char_traits
< wchar_t > >(
220 std::basic_ostream
< wchar_t, std::char_traits
< wchar_t > >& strm
,
221 attribute_name
const& name
);
224 BOOST_LOG_CLOSE_NAMESPACE
// namespace log
228 #include <boost/log/detail/footer.hpp>