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 global_logger_storage.cpp
9 * \author Andrey Semashev
10 * \date 21.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 <map>
18#include <string>
19#include <boost/limits.hpp>
20#include <boost/type_index.hpp>
21#include <boost/core/snprintf.hpp>
22#include <boost/log/exceptions.hpp>
23#include <boost/log/detail/singleton.hpp>
24#include <boost/log/sources/global_logger_storage.hpp>
25#if !defined(BOOST_LOG_NO_THREADS)
26#include <boost/thread/mutex.hpp>
27#include <boost/log/detail/locks.hpp>
28#endif
29#include <boost/log/detail/header.hpp>
30
31namespace boost {
32
33BOOST_LOG_OPEN_NAMESPACE
34
35namespace sources {
36
37namespace aux {
38
39BOOST_LOG_ANONYMOUS_NAMESPACE {
40
41//! The loggers repository singleton
42struct loggers_repository :
43 public log::aux::lazy_singleton< loggers_repository >
44{
45 //! Repository map type
46 typedef std::map< typeindex::type_index, shared_ptr< logger_holder_base > > loggers_map_t;
47
48#if !defined(BOOST_LOG_NO_THREADS)
49 //! Synchronization primitive
50 mutable mutex m_Mutex;
51#endif
52 //! Map of logger holders
53 loggers_map_t m_Loggers;
54};
55
56} // namespace
57
58//! Finds or creates the logger and returns its holder
59BOOST_LOG_API shared_ptr< logger_holder_base > global_storage::get_or_init(typeindex::type_index key, initializer_t initializer)
60{
61 typedef loggers_repository::loggers_map_t loggers_map_t;
62 loggers_repository& repo = loggers_repository::get();
63
64 BOOST_LOG_EXPR_IF_MT(log::aux::exclusive_lock_guard< mutex > lock(repo.m_Mutex);)
65 loggers_map_t::iterator it = repo.m_Loggers.find(x: key);
66 if (it != repo.m_Loggers.end())
67 {
68 // There is an instance
69 return it->second;
70 }
71 else
72 {
73 // We have to create a logger instance
74 shared_ptr< logger_holder_base > inst = initializer();
75 repo.m_Loggers[key] = inst;
76 return inst;
77 }
78}
79
80//! Throws the \c odr_violation exception
81BOOST_LOG_API BOOST_LOG_NORETURN void throw_odr_violation(
82 typeindex::type_index tag_type,
83 typeindex::type_index logger_type,
84 logger_holder_base const& registered)
85{
86 std::string str("Could not initialize global logger with tag \"");
87 str.append(str: tag_type.pretty_name());
88 str.append(s: "\" and type \"");
89 str.append(str: logger_type.pretty_name());
90 str.append(s: "\". A logger of type \"");
91 str.append(str: registered.m_LoggerType.pretty_name());
92 str.append(s: "\" with the same tag has already been registered at ");
93 str.append(s: registered.m_RegistrationFile);
94
95 char buf[std::numeric_limits< unsigned int >::digits10 + 3];
96 int res = boost::core::snprintf(s: buf, maxlen: sizeof(buf), format: "%u", registered.m_RegistrationLine);
97 if (BOOST_LIKELY(res > 0))
98 {
99 if (BOOST_UNLIKELY(static_cast< unsigned int >(res) >= sizeof(buf)))
100 res = sizeof(buf) - 1u;
101
102 str.push_back(c: ':');
103 str.append(s: buf, n: res);
104 }
105
106 str.push_back(c: '.');
107
108 BOOST_LOG_THROW_DESCR(odr_violation, str);
109}
110
111} // namespace aux
112
113} // namespace sources
114
115BOOST_LOG_CLOSE_NAMESPACE // namespace log
116
117} // namespace boost
118
119#include <boost/log/detail/footer.hpp>
120

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