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/log/exceptions.hpp>
22 #include <boost/log/detail/snprintf.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
31 namespace boost {
32
33 BOOST_LOG_OPEN_NAMESPACE
34
35 namespace sources {
36
37 namespace aux {
38
39 BOOST_LOG_ANONYMOUS_NAMESPACE {
40
41 //! The loggers repository singleton
42 struct 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
59 BOOST_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(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
throw_odr_violation(typeindex::type_index tag_type,typeindex::type_index logger_type,logger_holder_base const & registered)81 BOOST_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 char buf[std::numeric_limits< unsigned int >::digits10 + 3];
87 if (log::aux::snprintf(buf, sizeof(buf), "%u", registered.m_RegistrationLine) < 0)
88 buf[0] = '\0';
89 std::string str =
90 std::string("Could not initialize global logger with tag \"") +
91 tag_type.pretty_name() +
92 "\" and type \"" +
93 logger_type.pretty_name() +
94 "\". A logger of type \"" +
95 registered.m_LoggerType.pretty_name() +
96 "\" with the same tag has already been registered at " +
97 registered.m_RegistrationFile + ":" + buf + ".";
98
99 BOOST_LOG_THROW_DESCR(odr_violation, str);
100 }
101
102 } // namespace aux
103
104 } // namespace sources
105
106 BOOST_LOG_CLOSE_NAMESPACE // namespace log
107
108 } // namespace boost
109
110 #include <boost/log/detail/footer.hpp>
111