Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:26

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2015.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          http://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   global_logger_storage.hpp
0009  * \author Andrey Semashev
0010  * \date   21.04.2008
0011  *
0012  * The header contains implementation of facilities to declare global loggers.
0013  */
0014 
0015 #ifndef BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_
0016 #define BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_
0017 
0018 #include <stdexcept>
0019 #include <boost/type_index.hpp>
0020 #include <boost/smart_ptr/shared_ptr.hpp>
0021 #include <boost/smart_ptr/make_shared_object.hpp>
0022 #include <boost/preprocessor/seq/enum.hpp>
0023 #include <boost/log/detail/config.hpp>
0024 #include <boost/log/detail/singleton.hpp>
0025 #include <boost/log/detail/header.hpp>
0026 
0027 #ifdef BOOST_HAS_PRAGMA_ONCE
0028 #pragma once
0029 #endif
0030 
0031 namespace boost {
0032 
0033 BOOST_LOG_OPEN_NAMESPACE
0034 
0035 namespace sources {
0036 
0037 namespace aux {
0038 
0039 //! The base class for logger holders
0040 struct logger_holder_base
0041 {
0042     //! The source file name where the logger was registered
0043     const char* const m_RegistrationFile;
0044     //! The line number where the logger was registered
0045     const unsigned int m_RegistrationLine;
0046     //! Stored logger type
0047     const typeindex::type_index m_LoggerType;
0048 
0049     logger_holder_base(const char* file, unsigned int line, typeindex::type_index logger_type) BOOST_NOEXCEPT :
0050         m_RegistrationFile(file),
0051         m_RegistrationLine(line),
0052         m_LoggerType(logger_type)
0053     {
0054     }
0055 };
0056 
0057 //! The actual logger holder class
0058 template< typename LoggerT >
0059 struct logger_holder :
0060     public logger_holder_base
0061 {
0062     //! The logger instance
0063     LoggerT m_Logger;
0064 
0065     logger_holder(const char* file, unsigned int line, LoggerT const& logger) :
0066         logger_holder_base(file, line, typeindex::type_id< LoggerT >()),
0067         m_Logger(logger)
0068     {
0069     }
0070 
0071 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0072     logger_holder(const char* file, unsigned int line, LoggerT&& logger) :
0073         logger_holder_base(file, line, typeindex::type_id< LoggerT >()),
0074         m_Logger(static_cast< LoggerT&& >(logger))
0075     {
0076     }
0077 #endif
0078 };
0079 
0080 //! The class implements a global repository of tagged loggers
0081 struct global_storage
0082 {
0083     typedef shared_ptr< logger_holder_base >(*initializer_t)();
0084 
0085     //! Finds or creates the logger and returns its holder
0086     BOOST_LOG_API static shared_ptr< logger_holder_base > get_or_init(typeindex::type_index key, initializer_t initializer);
0087 
0088     //  Non-constructible, non-copyable, non-assignable
0089     BOOST_DELETED_FUNCTION(global_storage())
0090     BOOST_DELETED_FUNCTION(global_storage(global_storage const&))
0091     BOOST_DELETED_FUNCTION(global_storage& operator= (global_storage const&))
0092 };
0093 
0094 //! Throws the \c odr_violation exception
0095 BOOST_LOG_API BOOST_LOG_NORETURN void throw_odr_violation(
0096     typeindex::type_index tag_type,
0097     typeindex::type_index logger_type,
0098     logger_holder_base const& registered);
0099 
0100 //! The class implements a logger singleton
0101 template< typename TagT >
0102 struct logger_singleton :
0103     public boost::log::aux::lazy_singleton<
0104         logger_singleton< TagT >,
0105         shared_ptr< logger_holder< typename TagT::logger_type > >
0106     >
0107 {
0108     //! Base type
0109     typedef boost::log::aux::lazy_singleton<
0110         logger_singleton< TagT >,
0111         shared_ptr< logger_holder< typename TagT::logger_type > >
0112     > base_type;
0113     //! Logger type
0114     typedef typename TagT::logger_type logger_type;
0115 
0116     //! Returns the logger instance
0117     static logger_type& get()
0118     {
0119         return base_type::get()->m_Logger;
0120     }
0121 
0122     //! Initializes the logger instance (called only once)
0123     static void init_instance()
0124     {
0125         shared_ptr< logger_holder< logger_type > >& instance = base_type::get_instance();
0126         const typeindex::type_index tag_type_index = typeindex::type_id< TagT >();
0127         shared_ptr< logger_holder_base > holder = global_storage::get_or_init(tag_type_index, &logger_singleton::construct_logger);
0128         const typeindex::type_index logger_type_index = typeindex::type_id< logger_type >();
0129         if (holder->m_LoggerType == logger_type_index)
0130         {
0131             // Note: dynamic_cast may fail here if logger_type is not visible (for example, with Clang on Linux, if the original logger
0132             //       instance was initialized in a different DSO than where it's being queried). logger_holder visibility doesn't
0133             //       have effect since it is inhibited by the template parameter visibility.
0134             instance = boost::static_pointer_cast< logger_holder< logger_type > >(holder);
0135         }
0136         else
0137         {
0138             // In pure C++ this should never happen, since there cannot be two
0139             // different tag types that have equal type_infos. In real life it can
0140             // happen if the same-named tag is defined differently in two or more
0141             // dlls. This check is intended to detect such ODR violations. However, there
0142             // is no protection against different definitions of the logger type itself.
0143             boost::log::sources::aux::throw_odr_violation(tag_type_index, logger_type_index, *holder);
0144         }
0145     }
0146 
0147 private:
0148     //! Constructs a logger holder
0149     static shared_ptr< logger_holder_base > construct_logger()
0150     {
0151         return boost::make_shared< logger_holder< logger_type > >(
0152             TagT::registration_file(),
0153             static_cast< unsigned int >(TagT::registration_line),
0154             TagT::construct_logger());
0155     }
0156 };
0157 
0158 } // namespace aux
0159 
0160 //! The macro forward-declares a global logger with a custom initialization
0161 #define BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\
0162     struct tag_name\
0163     {\
0164         typedef logger logger_type;\
0165         enum registration_line_t { registration_line = __LINE__ };\
0166         static const char* registration_file() { return __FILE__; }\
0167         static logger_type construct_logger();\
0168         static inline logger_type& get()\
0169         {\
0170             return ::boost::log::sources::aux::logger_singleton< tag_name >::get();\
0171         }\
0172     };
0173 
0174 //! The macro defines a global logger initialization routine
0175 #define BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
0176     tag_name::logger_type tag_name::construct_logger()
0177 
0178 //! The macro defines a global logger initializer that will default-construct the logger
0179 #define BOOST_LOG_GLOBAL_LOGGER_DEFAULT(tag_name, logger)\
0180     BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
0181     {\
0182         return logger_type();\
0183     }
0184 
0185 //! The macro defines a global logger initializer that will construct the logger with the specified constructor arguments
0186 #define BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS(tag_name, logger, args)\
0187     BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
0188     {\
0189         return logger_type(BOOST_PP_SEQ_ENUM(args));\
0190     }
0191 
0192 //! The macro declares a global logger with a custom initialization
0193 #define BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
0194     BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\
0195     inline BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)
0196 
0197 //! The macro declares a global logger that will be default-constructed
0198 #define BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(tag_name, logger)\
0199     BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
0200     {\
0201         return logger_type();\
0202     }
0203 
0204 //! The macro declares a global logger that will be constructed with the specified arguments
0205 #define BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS(tag_name, logger, args)\
0206     BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
0207     {\
0208         return logger_type(BOOST_PP_SEQ_ENUM(args));\
0209     }
0210 
0211 } // namespace sources
0212 
0213 BOOST_LOG_CLOSE_NAMESPACE // namespace log
0214 
0215 } // namespace boost
0216 
0217 #include <boost/log/detail/footer.hpp>
0218 
0219 #endif // BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_