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