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