stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,742 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file basic_logger.hpp
* \author Andrey Semashev
* \date 08.03.2007
*
* The header contains implementation of a base class for loggers. Convenience macros
* for defining custom loggers are also provided.
*/
#ifndef BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_
#include <exception>
#include <utility>
#include <ostream>
#include <boost/assert.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/core/addressof.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/facilities/identity.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/parameter_tools.hpp>
#include <boost/log/attributes/attribute_set.hpp>
#include <boost/log/attributes/attribute_name.hpp>
#include <boost/log/attributes/attribute.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/core/record.hpp>
#include <boost/log/sources/features.hpp>
#include <boost/log/sources/threading_models.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
/*!
* \brief Basic logger class
*
* The \c basic_logger class template serves as a base class for all loggers
* provided by the library. It can also be used as a base for user-defined
* loggers. The template parameters are:
*
* \li \c CharT - logging character type
* \li \c FinalT - final type of the logger that eventually derives from
* the \c basic_logger. There may be other classes in the hierarchy
* between the final class and \c basic_logger.
* \li \c ThreadingModelT - threading model policy. Must provide methods
* of the Boost.Thread locking concept used in \c basic_logger class
* and all its derivatives in the hierarchy up to the \c FinalT class.
* The \c basic_logger class itself requires methods of the
* SharedLockable concept. The threading model policy must also be
* default and copy-constructible and support member function \c swap.
* There are currently two policies provided: \c single_thread_model
* and \c multi_thread_model.
*
* The logger implements fundamental facilities of loggers, such as storing
* source-specific attribute set and formatting log record messages. The basic
* logger interacts with the logging core in order to apply filtering and
* pass records to sinks.
*/
template< typename CharT, typename FinalT, typename ThreadingModelT >
class basic_logger :
public ThreadingModelT
{
typedef basic_logger this_type;
BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
public:
//! Character type
typedef CharT char_type;
//! Final logger type
typedef FinalT final_type;
//! Threading model type
typedef ThreadingModelT threading_model;
#if !defined(BOOST_LOG_NO_THREADS)
//! Lock requirement for the swap_unlocked method
typedef boost::log::aux::exclusive_lock_guard< threading_model > swap_lock;
//! Lock requirement for the add_attribute_unlocked method
typedef boost::log::aux::exclusive_lock_guard< threading_model > add_attribute_lock;
//! Lock requirement for the remove_attribute_unlocked method
typedef boost::log::aux::exclusive_lock_guard< threading_model > remove_attribute_lock;
//! Lock requirement for the remove_all_attributes_unlocked method
typedef boost::log::aux::exclusive_lock_guard< threading_model > remove_all_attributes_lock;
//! Lock requirement for the get_attributes method
typedef boost::log::aux::shared_lock_guard< const threading_model > get_attributes_lock;
//! Lock requirement for the open_record_unlocked method
typedef boost::log::aux::shared_lock_guard< threading_model > open_record_lock;
//! Lock requirement for the set_attributes method
typedef boost::log::aux::exclusive_lock_guard< threading_model > set_attributes_lock;
#else
typedef no_lock< threading_model > swap_lock;
typedef no_lock< threading_model > add_attribute_lock;
typedef no_lock< threading_model > remove_attribute_lock;
typedef no_lock< threading_model > remove_all_attributes_lock;
typedef no_lock< const threading_model > get_attributes_lock;
typedef no_lock< threading_model > open_record_lock;
typedef no_lock< threading_model > set_attributes_lock;
#endif
//! Lock requirement for the push_record_unlocked method
typedef no_lock< threading_model > push_record_lock;
private:
//! A pointer to the logging system
core_ptr m_pCore;
//! Logger-specific attribute set
attribute_set m_Attributes;
public:
/*!
* Constructor. Initializes internal data structures of the basic logger class,
* acquires reference to the logging core.
*/
basic_logger() :
threading_model(),
m_pCore(core::get())
{
}
/*!
* Copy constructor. Copies all attributes from the source logger.
*
* \note Not thread-safe. The source logger must be locked in the final class before copying.
*
* \param that Source logger
*/
basic_logger(basic_logger const& that) :
threading_model(static_cast< threading_model const& >(that)),
m_pCore(core::get()),
m_Attributes(that.m_Attributes)
{
}
/*!
* Move constructor. Moves all attributes from the source logger.
*
* \note Not thread-safe. The source logger must be locked in the final class before copying.
*
* \param that Source logger
*/
basic_logger(BOOST_RV_REF(basic_logger) that) :
threading_model(boost::move(static_cast< threading_model& >(that)))
{
m_pCore.swap(that.m_pCore);
m_Attributes.swap(that.m_Attributes);
}
/*!
* Constructor with named arguments. The constructor ignores all arguments. The result of
* construction is equivalent to default construction.
*/
template< typename ArgsT >
explicit basic_logger(ArgsT const&) :
threading_model(),
m_pCore(core::get())
{
}
protected:
/*!
* An accessor to the logging system pointer
*/
core_ptr const& core() const { return m_pCore; }
/*!
* An accessor to the logger attributes
*/
attribute_set& attributes() { return m_Attributes; }
/*!
* An accessor to the logger attributes
*/
attribute_set const& attributes() const { return m_Attributes; }
/*!
* An accessor to the threading model base
*/
threading_model& get_threading_model() { return *this; }
/*!
* An accessor to the threading model base
*/
threading_model const& get_threading_model() const { return *this; }
/*!
* An accessor to the final logger
*/
final_type* final_this()
{
BOOST_LOG_ASSUME(this != NULL);
return static_cast< final_type* >(this);
}
/*!
* An accessor to the final logger
*/
final_type const* final_this() const
{
BOOST_LOG_ASSUME(this != NULL);
return static_cast< final_type const* >(this);
}
/*!
* Unlocked \c swap
*/
void swap_unlocked(basic_logger& that)
{
get_threading_model().swap(that.get_threading_model());
m_Attributes.swap(that.m_Attributes);
}
/*!
* Unlocked \c add_attribute
*/
std::pair< attribute_set::iterator, bool > add_attribute_unlocked(attribute_name const& name, attribute const& attr)
{
return m_Attributes.insert(name, attr);
}
/*!
* Unlocked \c remove_attribute
*/
void remove_attribute_unlocked(attribute_set::iterator it)
{
m_Attributes.erase(it);
}
/*!
* Unlocked \c remove_all_attributes
*/
void remove_all_attributes_unlocked()
{
m_Attributes.clear();
}
/*!
* Unlocked \c open_record
*/
record open_record_unlocked()
{
return m_pCore->open_record(m_Attributes);
}
/*!
* Unlocked \c open_record
*/
template< typename ArgsT >
record open_record_unlocked(ArgsT const&)
{
return m_pCore->open_record(m_Attributes);
}
/*!
* Unlocked \c push_record
*/
void push_record_unlocked(BOOST_RV_REF(record) rec)
{
m_pCore->push_record(boost::move(rec));
}
/*!
* Unlocked \c get_attributes
*/
attribute_set get_attributes_unlocked() const
{
return m_Attributes;
}
/*!
* Unlocked \c set_attributes
*/
void set_attributes_unlocked(attribute_set const& attrs)
{
m_Attributes = attrs;
}
//! Assignment is closed (should be implemented through copy and swap in the final class)
BOOST_DELETED_FUNCTION(basic_logger& operator= (basic_logger const&))
};
/*!
* Free-standing swap for all loggers
*/
template< typename CharT, typename FinalT, typename ThreadingModelT >
inline void swap(
basic_logger< CharT, FinalT, ThreadingModelT >& left,
basic_logger< CharT, FinalT, ThreadingModelT >& right)
{
static_cast< FinalT& >(left).swap(static_cast< FinalT& >(right));
}
/*!
* \brief A composite logger that inherits a number of features
*
* The composite logger is a helper class that simplifies feature composition into the final logger.
* The user's logger class is expected to derive from the composite logger class, instantiated with
* the character type, the user's logger class, the threading model and the list of the required features.
* The former three parameters are passed to the \c basic_logger class template. The feature list
* must be an MPL type sequence, where each element is a unary MPL metafunction class, that upon
* applying on its argument results in a logging feature class that derives from the argument.
* Every logger feature provided by the library can participate in the feature list.
*/
template< typename CharT, typename FinalT, typename ThreadingModelT, typename FeaturesT >
class basic_composite_logger :
public boost::log::sources::aux::inherit_features<
basic_logger< CharT, FinalT, ThreadingModelT >,
FeaturesT
>::type
{
private:
//! Base type (the hierarchy of features)
typedef typename boost::log::sources::aux::inherit_features<
basic_logger< CharT, FinalT, ThreadingModelT >,
FeaturesT
>::type base_type;
protected:
//! The composite logger type (for use in the user's logger class)
typedef basic_composite_logger logger_base;
BOOST_COPYABLE_AND_MOVABLE_ALT(logger_base)
public:
//! Threading model being used
typedef typename base_type::threading_model threading_model;
#if !defined(BOOST_LOG_NO_THREADS)
public:
/*!
* Default constructor (default-constructs all features)
*/
basic_composite_logger() {}
/*!
* Copy constructor
*/
basic_composite_logger(basic_composite_logger const& that) :
base_type
((
boost::log::aux::shared_lock_guard< const threading_model >(that.get_threading_model()),
static_cast< base_type const& >(that)
))
{
}
/*!
* Move constructor
*/
basic_composite_logger(BOOST_RV_REF(logger_base) that) :
base_type(boost::move(static_cast< base_type& >(that)))
{
}
/*!
* Constructor with named parameters
*/
template< typename ArgsT >
explicit basic_composite_logger(ArgsT const& args) : base_type(args)
{
}
/*!
* The method adds an attribute to the source-specific attribute set. The attribute will be implicitly added to
* every log record made with the current logger.
*
* \param name The attribute name.
* \param attr The attribute factory.
* \return A pair of values. If the second member is \c true, then the attribute is added and the first member points to the
* attribute. Otherwise the attribute was not added and the first member points to the attribute that prevents
* addition.
*/
std::pair< attribute_set::iterator, bool > add_attribute(attribute_name const& name, attribute const& attr)
{
typename base_type::add_attribute_lock lock(base_type::get_threading_model());
return base_type::add_attribute_unlocked(name, attr);
}
/*!
* The method removes an attribute from the source-specific attribute set.
*
* \pre The attribute was added with the add_attribute call for this instance of the logger.
* \post The attribute is no longer registered as a source-specific attribute for this logger. The iterator is invalidated after removal.
*
* \param it Iterator to the previously added attribute.
*/
void remove_attribute(attribute_set::iterator it)
{
typename base_type::remove_attribute_lock lock(base_type::get_threading_model());
base_type::remove_attribute_unlocked(it);
}
/*!
* The method removes all attributes from the logger. All iterators and references to the removed attributes are invalidated.
*/
void remove_all_attributes()
{
typename base_type::remove_all_attributes_lock lock(base_type::get_threading_model());
base_type::remove_all_attributes_unlocked();
}
/*!
* The method retrieves a copy of a set with all attributes from the logger.
*
* \return The copy of the attribute set. Attributes are shallow-copied.
*/
attribute_set get_attributes() const
{
typename base_type::get_attributes_lock lock(base_type::get_threading_model());
return base_type::get_attributes_unlocked();
}
/*!
* The method installs the whole attribute set into the logger. All iterators and references to elements of
* the previous set are invalidated. Iterators to the \a attrs set are not valid to be used with the logger (that is,
* the logger owns a copy of \a attrs after completion).
*
* \param attrs The set of attributes to install into the logger. Attributes are shallow-copied.
*/
void set_attributes(attribute_set const& attrs)
{
typename base_type::set_attributes_lock lock(base_type::get_threading_model());
base_type::set_attributes_unlocked(attrs);
}
/*!
* The method opens a new log record in the logging core.
*
* \return A valid record handle if the logging record is opened successfully, an invalid handle otherwise.
*/
record open_record()
{
// Perform a quick check first
if (this->core()->get_logging_enabled())
{
typename base_type::open_record_lock lock(base_type::get_threading_model());
return base_type::open_record_unlocked(boost::log::aux::empty_arg_list());
}
else
return record();
}
/*!
* The method opens a new log record in the logging core.
*
* \param args A set of additional named arguments. The parameter is ignored.
* \return A valid record handle if the logging record is opened successfully, an invalid handle otherwise.
*/
template< typename ArgsT >
record open_record(ArgsT const& args)
{
// Perform a quick check first
if (this->core()->get_logging_enabled())
{
typename base_type::open_record_lock lock(base_type::get_threading_model());
return base_type::open_record_unlocked(args);
}
else
return record();
}
/*!
* The method pushes the constructed message to the logging core
*
* \param rec The log record with the formatted message
*/
void push_record(BOOST_RV_REF(record) rec)
{
typename base_type::push_record_lock lock(base_type::get_threading_model());
base_type::push_record_unlocked(boost::move(rec));
}
/*!
* Thread-safe implementation of swap
*/
void swap(basic_composite_logger& that)
{
boost::log::aux::multiple_unique_lock2<
threading_model,
threading_model
> lock(base_type::get_threading_model(), that.get_threading_model());
base_type::swap_unlocked(that);
}
protected:
/*!
* Assignment for the final class. Threadsafe, provides strong exception guarantee.
*/
FinalT& assign(FinalT const& that)
{
BOOST_LOG_ASSUME(this != NULL);
if (static_cast< FinalT* >(this) != boost::addressof(that))
{
// We'll have to explicitly create the copy in order to make sure it's unlocked when we attempt to lock *this
FinalT tmp(that);
boost::log::aux::exclusive_lock_guard< threading_model > lock(base_type::get_threading_model());
base_type::swap_unlocked(tmp);
}
return static_cast< FinalT& >(*this);
}
};
//! An optimized composite logger version with no multithreading support
template< typename CharT, typename FinalT, typename FeaturesT >
class basic_composite_logger< CharT, FinalT, single_thread_model, FeaturesT > :
public boost::log::sources::aux::inherit_features<
basic_logger< CharT, FinalT, single_thread_model >,
FeaturesT
>::type
{
private:
typedef typename boost::log::sources::aux::inherit_features<
basic_logger< CharT, FinalT, single_thread_model >,
FeaturesT
>::type base_type;
protected:
typedef basic_composite_logger logger_base;
BOOST_COPYABLE_AND_MOVABLE_ALT(logger_base)
public:
typedef typename base_type::threading_model threading_model;
#endif // !defined(BOOST_LOG_NO_THREADS)
public:
basic_composite_logger() {}
basic_composite_logger(basic_composite_logger const& that) :
base_type(static_cast< base_type const& >(that))
{
}
basic_composite_logger(BOOST_RV_REF(logger_base) that) :
base_type(boost::move(static_cast< base_type& >(that)))
{
}
template< typename ArgsT >
explicit basic_composite_logger(ArgsT const& args) : base_type(args)
{
}
std::pair< attribute_set::iterator, bool > add_attribute(attribute_name const& name, attribute const& attr)
{
return base_type::add_attribute_unlocked(name, attr);
}
void remove_attribute(attribute_set::iterator it)
{
base_type::remove_attribute_unlocked(it);
}
void remove_all_attributes()
{
base_type::remove_all_attributes_unlocked();
}
attribute_set get_attributes() const
{
return base_type::get_attributes_unlocked();
}
void set_attributes(attribute_set const& attrs)
{
base_type::set_attributes_unlocked(attrs);
}
record open_record()
{
// Perform a quick check first
if (this->core()->get_logging_enabled())
return base_type::open_record_unlocked(boost::log::aux::empty_arg_list());
else
return record();
}
template< typename ArgsT >
record open_record(ArgsT const& args)
{
// Perform a quick check first
if (this->core()->get_logging_enabled())
return base_type::open_record_unlocked(args);
else
return record();
}
void push_record(BOOST_RV_REF(record) rec)
{
base_type::push_record_unlocked(boost::move(rec));
}
void swap(basic_composite_logger& that)
{
base_type::swap_unlocked(that);
}
protected:
FinalT& assign(FinalT that)
{
base_type::swap_unlocked(that);
return static_cast< FinalT& >(*this);
}
};
#ifndef BOOST_LOG_DOXYGEN_PASS
#define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, typename_keyword)\
public:\
BOOST_DEFAULTED_FUNCTION(class_type(), {})\
class_type(class_type const& that) : class_type::logger_base(\
static_cast< typename_keyword() class_type::logger_base const& >(that)) {}\
class_type(BOOST_RV_REF(class_type) that) : class_type::logger_base(\
::boost::move(static_cast< typename_keyword() class_type::logger_base& >(that))) {}\
BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_FORWARD(class_type, class_type::logger_base)\
#endif // BOOST_LOG_DOXYGEN_PASS
#define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS(class_type)\
BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, BOOST_PP_EMPTY)
#define BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_TEMPLATE(class_type)\
BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_IMPL(class_type, BOOST_PP_IDENTITY(typename))
#define BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT(class_type)\
public:\
class_type& operator= (BOOST_COPY_ASSIGN_REF(class_type) that)\
{\
return class_type::logger_base::assign(static_cast< class_type const& >(that));\
}\
class_type& operator= (BOOST_RV_REF(class_type) that)\
{\
BOOST_LOG_EXPR_IF_MT(::boost::log::aux::exclusive_lock_guard< class_type::threading_model > lock(this->get_threading_model());)\
this->swap_unlocked(that);\
return *this;\
}
#define BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT_TEMPLATE(class_type)\
public:\
class_type& operator= (BOOST_COPY_ASSIGN_REF(class_type) that)\
{\
return class_type::logger_base::assign(static_cast< class_type const& >(that));\
}\
class_type& operator= (BOOST_RV_REF(class_type) that)\
{\
BOOST_LOG_EXPR_IF_MT(::boost::log::aux::exclusive_lock_guard< typename class_type::threading_model > lock(this->get_threading_model());)\
this->swap_unlocked(that);\
return *this;\
}
#define BOOST_LOG_FORWARD_LOGGER_MEMBERS(class_type)\
BOOST_COPYABLE_AND_MOVABLE(class_type)\
BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS(class_type)\
BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT(class_type)
#define BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(class_type)\
BOOST_COPYABLE_AND_MOVABLE(class_type)\
BOOST_LOG_FORWARD_LOGGER_CONSTRUCTORS_TEMPLATE(class_type)\
BOOST_LOG_FORWARD_LOGGER_ASSIGNMENT_TEMPLATE(class_type)
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
/*!
* \brief The macro declares a logger class that inherits a number of base classes
*
* \param type_name The name of the logger class to declare
* \param char_type The character type of the logger. Either char or wchar_t expected.
* \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
* \param threading A threading model class
*/
#define BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char_type, base_seq, threading)\
class type_name :\
public ::boost::log::sources::basic_composite_logger<\
char_type,\
type_name,\
threading,\
::boost::log::sources::features< BOOST_PP_SEQ_ENUM(base_seq) >\
>\
{\
BOOST_LOG_FORWARD_LOGGER_MEMBERS(type_name)\
}
#ifdef BOOST_LOG_USE_CHAR
/*!
* \brief The macro declares a narrow-char logger class that inherits a number of base classes
*
* Equivalent to BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, single_thread_model)
*
* \param type_name The name of the logger class to declare
* \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
*/
#define BOOST_LOG_DECLARE_LOGGER(type_name, base_seq)\
BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, ::boost::log::sources::single_thread_model)
#if !defined(BOOST_LOG_NO_THREADS)
/*!
* \brief The macro declares a narrow-char thread-safe logger class that inherits a number of base classes
*
* Equivalent to <tt>BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq, multi_thread_model< shared_mutex >)</tt>
*
* \param type_name The name of the logger class to declare
* \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
*/
#define BOOST_LOG_DECLARE_LOGGER_MT(type_name, base_seq)\
BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, char, base_seq,\
::boost::log::sources::multi_thread_model< ::boost::shared_mutex >)
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif // BOOST_LOG_USE_CHAR
#ifdef BOOST_LOG_USE_WCHAR_T
/*!
* \brief The macro declares a wide-char logger class that inherits a number of base classes
*
* Equivalent to BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, single_thread_model)
*
* \param type_name The name of the logger class to declare
* \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
*/
#define BOOST_LOG_DECLARE_WLOGGER(type_name, base_seq)\
BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, ::boost::log::sources::single_thread_model)
#if !defined(BOOST_LOG_NO_THREADS)
/*!
* \brief The macro declares a wide-char thread-safe logger class that inherits a number of base classes
*
* Equivalent to <tt>BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq, multi_thread_model< shared_mutex >)</tt>
*
* \param type_name The name of the logger class to declare
* \param base_seq A Boost.Preprocessor sequence of type identifiers of the base classes templates
*/
#define BOOST_LOG_DECLARE_WLOGGER_MT(type_name, base_seq)\
BOOST_LOG_DECLARE_LOGGER_TYPE(type_name, wchar_t, base_seq,\
::boost::log::sources::multi_thread_model< ::boost::shared_mutex >)
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif // BOOST_LOG_USE_WCHAR_T
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_BASIC_LOGGER_HPP_INCLUDED_
@@ -0,0 +1,242 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file channel_feature.hpp
* \author Andrey Semashev
* \date 28.02.2008
*
* The header contains implementation of a channel support feature.
*/
#ifndef BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_
#include <string>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/locks.hpp>
#include <boost/log/detail/default_attribute_names.hpp>
#include <boost/log/keywords/channel.hpp>
#include <boost/log/attributes/mutable_constant.hpp>
#include <boost/log/utility/strictest_lock.hpp>
#include <boost/log/core/record.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
/*!
* \brief Channel feature implementation
*/
template< typename BaseT, typename ChannelT >
class basic_channel_logger :
public BaseT
{
//! Base type
typedef BaseT base_type;
typedef basic_channel_logger this_type;
BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
public:
//! Character type
typedef typename base_type::char_type char_type;
//! Final type
typedef typename base_type::final_type final_type;
//! Threading model being used
typedef typename base_type::threading_model threading_model;
//! Channel type
typedef ChannelT channel_type;
//! Channel attribute type
typedef attributes::mutable_constant< channel_type > channel_attribute;
//! Lock requirement for the \c open_record_unlocked method
typedef typename strictest_lock<
typename base_type::open_record_lock,
#ifndef BOOST_LOG_NO_THREADS
boost::log::aux::exclusive_lock_guard< threading_model >
#else
no_lock< threading_model >
#endif // !defined(BOOST_LOG_NO_THREADS)
>::type open_record_lock;
//! Lock requirement for the \c swap_unlocked method
typedef typename strictest_lock<
typename base_type::swap_lock,
#ifndef BOOST_LOG_NO_THREADS
boost::log::aux::exclusive_lock_guard< threading_model >
#else
no_lock< threading_model >
#endif // !defined(BOOST_LOG_NO_THREADS)
>::type swap_lock;
private:
//! Default channel name generator
struct make_default_channel_name
{
typedef channel_type result_type;
result_type operator() () const { return result_type(); }
};
private:
//! Channel attribute
channel_attribute m_ChannelAttr;
public:
/*!
* Default constructor. The constructed logger has the default-constructed channel name.
*/
basic_channel_logger() : base_type(), m_ChannelAttr(channel_type())
{
base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::channel(), m_ChannelAttr);
}
/*!
* Copy constructor
*/
basic_channel_logger(basic_channel_logger const& that) :
base_type(static_cast< base_type const& >(that)),
m_ChannelAttr(that.m_ChannelAttr)
{
base_type::attributes()[boost::log::aux::default_attribute_names::channel()] = m_ChannelAttr;
}
/*!
* Move constructor
*/
basic_channel_logger(BOOST_RV_REF(basic_channel_logger) that) :
base_type(boost::move(static_cast< base_type& >(that))),
m_ChannelAttr(boost::move(that.m_ChannelAttr))
{
base_type::attributes()[boost::log::aux::default_attribute_names::channel()] = m_ChannelAttr;
}
/*!
* Constructor with arguments. Allows to register a channel name attribute on construction.
*
* \param args A set of named arguments. The following arguments are supported:
* \li \c channel - a string that represents the channel name
*/
template< typename ArgsT >
explicit basic_channel_logger(ArgsT const& args) :
base_type(args),
m_ChannelAttr(args[keywords::channel || make_default_channel_name()])
{
base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::channel(), m_ChannelAttr);
}
/*!
* The observer of the channel name
*
* \return The channel name that was set by the logger
*/
channel_type channel() const
{
BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< const threading_model > lock(this->get_threading_model());)
return m_ChannelAttr.get();
}
/*!
* The setter of the channel name
*
* \param ch The channel name to be set for the logger
*/
void channel(channel_type const& ch)
{
BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< threading_model > lock(this->get_threading_model());)
m_ChannelAttr.set(ch);
}
protected:
/*!
* Channel attribute accessor
*/
channel_attribute const& get_channel_attribute() const { return m_ChannelAttr; }
/*!
* Unlocked \c open_record
*/
template< typename ArgsT >
record open_record_unlocked(ArgsT const& args)
{
return open_record_with_channel_unlocked(args, args[keywords::channel | parameter::void_()]);
}
/*!
* Unlocked swap
*/
void swap_unlocked(basic_channel_logger& that)
{
base_type::swap_unlocked(static_cast< base_type& >(that));
m_ChannelAttr.swap(that.m_ChannelAttr);
}
private:
//! The \c open_record implementation for the case when the channel is specified in log statement
template< typename ArgsT, typename T >
record open_record_with_channel_unlocked(ArgsT const& args, T const& ch)
{
m_ChannelAttr.set(ch);
return base_type::open_record_unlocked(args);
}
//! The \c open_record implementation for the case when the channel is not specified in log statement
template< typename ArgsT >
record open_record_with_channel_unlocked(ArgsT const& args, parameter::void_)
{
return base_type::open_record_unlocked(args);
}
};
/*!
* \brief Channel support feature
*
* The logger with this feature automatically registers an attribute with the specified
* on construction value, which is a channel name. The channel name can be modified
* through the logger life time, either by calling the \c channel method or by specifying
* the name in the logging statement.
*
* The type of the channel name can be customized by providing it as a template parameter
* to the feature template. By default, a string will be used.
*/
template< typename ChannelT = std::string >
struct channel
{
template< typename BaseT >
struct apply
{
typedef basic_channel_logger<
BaseT,
ChannelT
> type;
};
};
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
//! The macro allows to put a record with a specific channel name into log
#define BOOST_LOG_STREAM_CHANNEL(logger, chan)\
BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::channel = (chan)))
#ifndef BOOST_LOG_NO_SHORTHAND_NAMES
//! An equivalent to BOOST_LOG_STREAM_CHANNEL(logger, chan)
#define BOOST_LOG_CHANNEL(logger, chan) BOOST_LOG_STREAM_CHANNEL(logger, chan)
#endif // BOOST_LOG_NO_SHORTHAND_NAMES
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_CHANNEL_FEATURE_HPP_INCLUDED_
@@ -0,0 +1,325 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file channel_logger.hpp
* \author Andrey Semashev
* \date 28.02.2008
*
* The header contains implementation of a logger with channel support.
*/
#ifndef BOOST_LOG_SOURCES_CHANNEL_LOGGER_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_CHANNEL_LOGGER_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/detail/light_rw_mutex.hpp>
#endif // !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/sources/features.hpp>
#include <boost/log/sources/basic_logger.hpp>
#include <boost/log/sources/threading_models.hpp>
#include <boost/log/sources/channel_feature.hpp>
#include <boost/log/keywords/channel.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
#ifndef BOOST_LOG_DOXYGEN_PASS
#ifdef BOOST_LOG_USE_CHAR
//! Narrow-char logger with channel support
template< typename ChannelT = std::string >
class channel_logger :
public basic_composite_logger<
char,
channel_logger< ChannelT >,
single_thread_model,
features< channel< ChannelT > >
>
{
typedef typename channel_logger::logger_base base_type;
public:
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(channel_logger)
explicit channel_logger(ChannelT const& channel) : base_type(keywords::channel = channel)
{
}
};
#if !defined(BOOST_LOG_NO_THREADS)
//! Narrow-char thread-safe logger with channel support
template< typename ChannelT = std::string >
class channel_logger_mt :
public basic_composite_logger<
char,
channel_logger_mt< ChannelT >,
multi_thread_model< boost::log::aux::light_rw_mutex >,
features< channel< ChannelT > >
>
{
typedef typename channel_logger_mt::logger_base base_type;
public:
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(channel_logger_mt)
explicit channel_logger_mt(ChannelT const& channel) : base_type(keywords::channel = channel)
{
}
};
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif // BOOST_LOG_USE_CHAR
#ifdef BOOST_LOG_USE_WCHAR_T
//! Wide-char logger with channel support
template< typename ChannelT = std::wstring >
class wchannel_logger :
public basic_composite_logger<
wchar_t,
wchannel_logger< ChannelT >,
single_thread_model,
features< channel< ChannelT > >
>
{
typedef typename wchannel_logger::logger_base base_type;
public:
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wchannel_logger)
explicit wchannel_logger(ChannelT const& channel) : base_type(keywords::channel = channel)
{
}
};
#if !defined(BOOST_LOG_NO_THREADS)
//! Wide-char thread-safe logger with channel support
template< typename ChannelT = std::wstring >
class wchannel_logger_mt :
public basic_composite_logger<
wchar_t,
wchannel_logger< ChannelT >,
multi_thread_model< boost::log::aux::light_rw_mutex >,
features< channel< ChannelT > >
>
{
typedef typename wchannel_logger_mt::logger_base base_type;
public:
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wchannel_logger_mt)
explicit wchannel_logger_mt(ChannelT const& channel) : base_type(keywords::channel = channel)
{
}
};
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif // BOOST_LOG_USE_WCHAR_T
#else // BOOST_LOG_DOXYGEN_PASS
/*!
* \brief Narrow-char logger. Functionally equivalent to \c basic_channel_logger.
*
* See \c channel class template for a more detailed description
*/
template< typename ChannelT = std::string >
class channel_logger :
public basic_composite_logger<
char,
channel_logger< ChannelT >,
single_thread_model,
features< channel< ChannelT > >
>
{
public:
/*!
* Default constructor
*/
channel_logger();
/*!
* Copy constructor
*/
channel_logger(channel_logger const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit channel_logger(ArgsT... const& args);
/*!
* The constructor creates the logger with the specified channel name
*
* \param channel The channel name
*/
explicit channel_logger(ChannelT const& channel);
/*!
* Assignment operator
*/
channel_logger& operator= (channel_logger const& that)
/*!
* Swaps two loggers
*/
void swap(channel_logger& that);
};
/*!
* \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_channel_logger.
*
* See \c channel class template for a more detailed description
*/
template< typename ChannelT = std::string >
class channel_logger_mt :
public basic_composite_logger<
char,
channel_logger_mt< ChannelT >,
multi_thread_model< implementation_defined >,
features< channel< ChannelT > >
>
{
public:
/*!
* Default constructor
*/
channel_logger_mt();
/*!
* Copy constructor
*/
channel_logger_mt(channel_logger_mt const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit channel_logger_mt(ArgsT... const& args);
/*!
* The constructor creates the logger with the specified channel name
*
* \param channel The channel name
*/
explicit channel_logger_mt(ChannelT const& channel);
/*!
* Assignment operator
*/
channel_logger_mt& operator= (channel_logger_mt const& that)
/*!
* Swaps two loggers
*/
void swap(channel_logger_mt& that);
};
/*!
* \brief Wide-char logger. Functionally equivalent to \c basic_channel_logger.
*
* See \c channel class template for a more detailed description
*/
template< typename ChannelT = std::wstring >
class wchannel_logger :
public basic_composite_logger<
wchar_t,
wchannel_logger< ChannelT >,
single_thread_model,
features< channel< ChannelT > >
>
{
public:
/*!
* Default constructor
*/
wchannel_logger();
/*!
* Copy constructor
*/
wchannel_logger(wchannel_logger const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit wchannel_logger(ArgsT... const& args);
/*!
* The constructor creates the logger with the specified channel name
*
* \param channel The channel name
*/
explicit wchannel_logger(ChannelT const& channel);
/*!
* Assignment operator
*/
wchannel_logger& operator= (wchannel_logger const& that)
/*!
* Swaps two loggers
*/
void swap(wchannel_logger& that);
};
/*!
* \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_channel_logger.
*
* See \c channel class template for a more detailed description
*/
template< typename ChannelT = std::wstring >
class wchannel_logger_mt :
public basic_composite_logger<
wchar_t,
wchannel_logger< ChannelT >,
multi_thread_model< implementation_defined >,
features< channel< ChannelT > >
>
{
public:
/*!
* Default constructor
*/
wchannel_logger_mt();
/*!
* Copy constructor
*/
wchannel_logger_mt(wchannel_logger_mt const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit wchannel_logger_mt(ArgsT... const& args);
/*!
* The constructor creates the logger with the specified channel name
*
* \param channel The channel name
*/
explicit wchannel_logger_mt(ChannelT const& channel);
/*!
* Assignment operator
*/
wchannel_logger_mt& operator= (wchannel_logger_mt const& that)
/*!
* Swaps two loggers
*/
void swap(wchannel_logger_mt& that);
};
#endif // BOOST_LOG_DOXYGEN_PASS
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_CHANNEL_LOGGER_HPP_INCLUDED_
@@ -0,0 +1,253 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file exception_handler_feature.hpp
* \author Andrey Semashev
* \date 17.07.2009
*
* The header contains implementation of an exception handler support feature.
*/
#ifndef BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_
#include <boost/mpl/if.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/light_function.hpp>
#include <boost/log/detail/locks.hpp>
#include <boost/log/core/record.hpp>
#include <boost/log/sources/threading_models.hpp>
#include <boost/log/utility/strictest_lock.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/thread/exceptions.hpp>
#endif
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
/*!
* \brief Exception handler feature implementation
*/
template< typename BaseT >
class basic_exception_handler_logger :
public BaseT
{
//! Base type
typedef BaseT base_type;
typedef basic_exception_handler_logger this_type;
BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
public:
//! Threading model being used
typedef typename base_type::threading_model threading_model;
//! Final logger type
typedef typename base_type::final_type final_type;
//! Exception handler function type
typedef boost::log::aux::light_function< void () > exception_handler_type;
#if defined(BOOST_LOG_DOXYGEN_PASS)
//! Lock requirement for the open_record_unlocked method
typedef typename strictest_lock<
typename base_type::open_record_lock,
no_lock< threading_model >
>::type open_record_lock;
//! Lock requirement for the push_record_unlocked method
typedef typename strictest_lock<
typename base_type::push_record_lock,
no_lock< threading_model >
>::type push_record_lock;
#endif // defined(BOOST_LOG_DOXYGEN_PASS)
//! Lock requirement for the swap_unlocked method
typedef typename strictest_lock<
typename base_type::swap_lock,
#ifndef BOOST_LOG_NO_THREADS
boost::log::aux::exclusive_lock_guard< threading_model >
#else
no_lock< threading_model >
#endif // !defined(BOOST_LOG_NO_THREADS)
>::type swap_lock;
private:
//! Exception handler
exception_handler_type m_ExceptionHandler;
public:
/*!
* Default constructor. The constructed logger does not have an exception handler.
*/
basic_exception_handler_logger() : base_type()
{
}
/*!
* Copy constructor
*/
basic_exception_handler_logger(basic_exception_handler_logger const& that) :
base_type(static_cast< base_type const& >(that)),
m_ExceptionHandler(that.m_ExceptionHandler)
{
}
/*!
* Move constructor
*/
basic_exception_handler_logger(BOOST_RV_REF(basic_exception_handler_logger) that) :
base_type(boost::move(static_cast< base_type& >(that))),
m_ExceptionHandler(boost::move(that.m_ExceptionHandler))
{
}
/*!
* Constructor with arguments. Passes arguments to other features.
*/
template< typename ArgsT >
explicit basic_exception_handler_logger(ArgsT const& args) :
base_type(args)
{
}
/*!
* The method sets exception handler function. The function will be called with no arguments
* in case if an exception occurs during either \c open_record or \c push_record method
* execution. Since exception handler is called from a \c catch statement, the exception
* can be rethrown in order to determine its type.
*
* By default no handler is installed, thus any exception is propagated as usual.
*
* \sa <tt>utility/exception_handler.hpp</tt>
* \param handler Exception handling function
*
* \note The exception handler can be invoked in several threads concurrently.
*
* \note Thread interruptions are not affected by exception handlers.
*/
template< typename HandlerT >
void set_exception_handler(HandlerT const& handler)
{
#ifndef BOOST_LOG_NO_THREADS
boost::log::aux::exclusive_lock_guard< threading_model > lock(this->get_threading_model());
#endif
m_ExceptionHandler = handler;
}
protected:
/*!
* Unlocked \c open_record
*/
template< typename ArgsT >
record open_record_unlocked(ArgsT const& args)
{
try
{
return base_type::open_record_unlocked(args);
}
#ifndef BOOST_LOG_NO_THREADS
catch (thread_interrupted&)
{
throw;
}
#endif
catch (...)
{
handle_exception();
return record();
}
}
/*!
* Unlocked \c push_record
*/
void push_record_unlocked(BOOST_RV_REF(record) rec)
{
try
{
base_type::push_record_unlocked(boost::move(rec));
}
#ifndef BOOST_LOG_NO_THREADS
catch (thread_interrupted&)
{
throw;
}
#endif
catch (...)
{
handle_exception();
}
}
/*!
* Unlocked swap
*/
void swap_unlocked(basic_exception_handler_logger& that)
{
base_type::swap_unlocked(static_cast< base_type& >(that));
m_ExceptionHandler.swap(that.m_ExceptionHandler);
}
private:
#if !defined(BOOST_LOG_DOXYGEN_PASS)
//! The function handles the intercepted exception
void handle_exception()
{
#ifndef BOOST_LOG_NO_THREADS
// Here's the trick with the lock type. Since the lock
// is only needed when an exception is caught, we indicate
// no locking requirements in the push_record_lock type.
// However, if other features don't require locking either,
// we shall acquire a read lock here, when an exception is caught.
// If other features do require locking, the thread model is
// already locked by now, and we don't do locking at all.
typedef typename mpl::if_<
is_same< no_lock< threading_model >, typename final_type::push_record_lock >,
boost::log::aux::shared_lock_guard< threading_model >,
no_lock< threading_model >
>::type lock_type;
lock_type lock(base_type::get_threading_model());
#endif // !defined(BOOST_LOG_NO_THREADS)
if (m_ExceptionHandler.empty())
throw;
m_ExceptionHandler();
}
#endif // !defined(BOOST_LOG_DOXYGEN_PASS)
};
/*!
* \brief Exception handler support feature
*
* The logger with this feature will provide an additional method to
* install an exception handler functional object. This functional
* object will be called if during either opening or pushing a record
* an exception is thrown from the logging core.
*/
struct exception_handler
{
template< typename BaseT >
struct apply
{
typedef basic_exception_handler_logger< BaseT > type;
};
};
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_EXCEPTION_HANDLER_FEATURE_HPP_INCLUDED_
@@ -0,0 +1,150 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file sources/features.hpp
* \author Andrey Semashev
* \date 17.07.2009
*
* The header contains definition of a features list class template.
*/
#ifndef BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
#include <boost/mpl/lambda.hpp>
#include <boost/log/detail/config.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
//! The macro defines the maximum number of features that can be specified for a logger
#ifndef BOOST_LOG_FEATURES_LIMIT
#define BOOST_LOG_FEATURES_LIMIT 10
#endif // BOOST_LOG_FEATURES_LIMIT
#endif
#include <boost/log/detail/header.hpp>
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
#if defined(BOOST_LOG_DOXYGEN_PASS) || !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
/*!
* \brief A type sequence of logger features
*
* This class template can be used to specify logger features in a \c basic_composite_logger instantiation.
*/
template< typename... FeaturesT >
struct features
{
};
namespace aux {
//! The metafunction produces the inherited features hierarchy with \c RootT as the ultimate base type
template< typename RootT, typename FeaturesT >
struct inherit_features;
template< typename RootT, typename FeatureT0, typename... FeaturesT >
struct inherit_features< RootT, features< FeatureT0, FeaturesT... > >
{
typedef typename mpl::lambda<
FeatureT0
>::type::BOOST_NESTED_TEMPLATE apply<
typename inherit_features<
RootT,
features< FeaturesT... >
>::type
>::type type;
};
template< typename RootT, typename FeatureT0 >
struct inherit_features< RootT, features< FeatureT0 > >
{
typedef typename mpl::lambda<
FeatureT0
>::type::BOOST_NESTED_TEMPLATE apply<
RootT
>::type type;
};
template< typename RootT >
struct inherit_features< RootT, features< > >
{
typedef RootT type;
};
} // namespace aux
#else
//! A type sequence of logger features
template< BOOST_PP_ENUM_BINARY_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT, = void BOOST_PP_INTERCEPT) >
struct features
{
};
namespace aux {
template< typename RootT, typename FeaturesT >
struct inherit_features;
template< typename RootT, BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, typename FeatureT) >
struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) > >
{
typedef typename mpl::lambda<
FeatureT0
>::type::BOOST_NESTED_TEMPLATE apply<
typename inherit_features<
RootT,
features< BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, FeatureT) >
>::type
>::type type;
};
template< typename RootT, typename FeatureT0 >
struct inherit_features< RootT, features< FeatureT0, BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > >
{
typedef typename mpl::lambda<
FeatureT0
>::type::BOOST_NESTED_TEMPLATE apply<
RootT
>::type type;
};
template< typename RootT >
struct inherit_features< RootT, features< BOOST_PP_ENUM_PARAMS(BOOST_LOG_FEATURES_LIMIT, void BOOST_PP_INTERCEPT) > >
{
typedef RootT type;
};
} // namespace aux
#endif
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_FEATURES_HPP_INCLUDED_
@@ -0,0 +1,219 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file global_logger_storage.hpp
* \author Andrey Semashev
* \date 21.04.2008
*
* The header contains implementation of facilities to declare global loggers.
*/
#ifndef BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_
#include <stdexcept>
#include <boost/type_index.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/singleton.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
namespace aux {
//! The base class for logger holders
struct logger_holder_base
{
//! The source file name where the logger was registered
const char* const m_RegistrationFile;
//! The line number where the logger was registered
const unsigned int m_RegistrationLine;
//! Stored logger type
const typeindex::type_index m_LoggerType;
logger_holder_base(const char* file, unsigned int line, typeindex::type_index logger_type) BOOST_NOEXCEPT :
m_RegistrationFile(file),
m_RegistrationLine(line),
m_LoggerType(logger_type)
{
}
};
//! The actual logger holder class
template< typename LoggerT >
struct logger_holder :
public logger_holder_base
{
//! The logger instance
LoggerT m_Logger;
logger_holder(const char* file, unsigned int line, LoggerT const& logger) :
logger_holder_base(file, line, typeindex::type_id< LoggerT >()),
m_Logger(logger)
{
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
logger_holder(const char* file, unsigned int line, LoggerT&& logger) :
logger_holder_base(file, line, typeindex::type_id< LoggerT >()),
m_Logger(static_cast< LoggerT&& >(logger))
{
}
#endif
};
//! The class implements a global repository of tagged loggers
struct global_storage
{
typedef shared_ptr< logger_holder_base >(*initializer_t)();
//! Finds or creates the logger and returns its holder
BOOST_LOG_API static shared_ptr< logger_holder_base > get_or_init(typeindex::type_index key, initializer_t initializer);
// Non-constructible, non-copyable, non-assignable
BOOST_DELETED_FUNCTION(global_storage())
BOOST_DELETED_FUNCTION(global_storage(global_storage const&))
BOOST_DELETED_FUNCTION(global_storage& operator= (global_storage const&))
};
//! Throws the \c odr_violation exception
BOOST_LOG_API BOOST_LOG_NORETURN void throw_odr_violation(
typeindex::type_index tag_type,
typeindex::type_index logger_type,
logger_holder_base const& registered);
//! The class implements a logger singleton
template< typename TagT >
struct logger_singleton :
public boost::log::aux::lazy_singleton<
logger_singleton< TagT >,
shared_ptr< logger_holder< typename TagT::logger_type > >
>
{
//! Base type
typedef boost::log::aux::lazy_singleton<
logger_singleton< TagT >,
shared_ptr< logger_holder< typename TagT::logger_type > >
> base_type;
//! Logger type
typedef typename TagT::logger_type logger_type;
//! Returns the logger instance
static logger_type& get()
{
return base_type::get()->m_Logger;
}
//! Initializes the logger instance (called only once)
static void init_instance()
{
shared_ptr< logger_holder< logger_type > >& instance = base_type::get_instance();
const typeindex::type_index tag_type_index = typeindex::type_id< TagT >();
shared_ptr< logger_holder_base > holder = global_storage::get_or_init(tag_type_index, &logger_singleton::construct_logger);
const typeindex::type_index logger_type_index = typeindex::type_id< logger_type >();
if (holder->m_LoggerType == logger_type_index)
{
// Note: dynamic_cast may fail here if logger_type is not visible (for example, with Clang on Linux, if the original logger
// instance was initialized in a different DSO than where it's being queried). logger_holder visibility doesn't
// have effect since it is inhibited by the template parameter visibility.
instance = boost::static_pointer_cast< logger_holder< logger_type > >(holder);
}
else
{
// In pure C++ this should never happen, since there cannot be two
// different tag types that have equal type_infos. In real life it can
// happen if the same-named tag is defined differently in two or more
// dlls. This check is intended to detect such ODR violations. However, there
// is no protection against different definitions of the logger type itself.
boost::log::sources::aux::throw_odr_violation(tag_type_index, logger_type_index, *holder);
}
}
private:
//! Constructs a logger holder
static shared_ptr< logger_holder_base > construct_logger()
{
return boost::make_shared< logger_holder< logger_type > >(
TagT::registration_file(),
static_cast< unsigned int >(TagT::registration_line),
TagT::construct_logger());
}
};
} // namespace aux
//! The macro forward-declares a global logger with a custom initialization
#define BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\
struct tag_name\
{\
typedef logger logger_type;\
enum registration_line_t { registration_line = __LINE__ };\
static const char* registration_file() { return __FILE__; }\
static logger_type construct_logger();\
static inline logger_type& get()\
{\
return ::boost::log::sources::aux::logger_singleton< tag_name >::get();\
}\
};
//! The macro defines a global logger initialization routine
#define BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
tag_name::logger_type tag_name::construct_logger()
//! The macro defines a global logger initializer that will default-construct the logger
#define BOOST_LOG_GLOBAL_LOGGER_DEFAULT(tag_name, logger)\
BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
{\
return logger_type();\
}
//! The macro defines a global logger initializer that will construct the logger with the specified constructor arguments
#define BOOST_LOG_GLOBAL_LOGGER_CTOR_ARGS(tag_name, logger, args)\
BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)\
{\
return logger_type(BOOST_PP_SEQ_ENUM(args));\
}
//! The macro declares a global logger with a custom initialization
#define BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
BOOST_LOG_GLOBAL_LOGGER(tag_name, logger)\
inline BOOST_LOG_GLOBAL_LOGGER_INIT(tag_name, logger)
//! The macro declares a global logger that will be default-constructed
#define BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(tag_name, logger)\
BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
{\
return logger_type();\
}
//! The macro declares a global logger that will be constructed with the specified arguments
#define BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS(tag_name, logger, args)\
BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(tag_name, logger)\
{\
return logger_type(BOOST_PP_SEQ_ENUM(args));\
}
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_GLOBAL_LOGGER_STORAGE_HPP_INCLUDED_
@@ -0,0 +1,103 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file logger.hpp
* \author Andrey Semashev
* \date 08.03.2007
*
* The header contains implementation of a simplistic logger with no features.
*/
#ifndef BOOST_LOG_SOURCES_LOGGER_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_LOGGER_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/sources/basic_logger.hpp>
#include <boost/log/sources/features.hpp>
#include <boost/log/sources/threading_models.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/detail/light_rw_mutex.hpp>
#endif // !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
#ifdef BOOST_LOG_USE_CHAR
/*!
* \brief Narrow-char logger. Functionally equivalent to \c basic_logger.
*
* See \c basic_logger class template for a more detailed description.
*/
class logger :
public basic_composite_logger< char, logger, single_thread_model, features< > >
{
BOOST_LOG_FORWARD_LOGGER_MEMBERS(logger)
};
#if !defined(BOOST_LOG_NO_THREADS)
/*!
* \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_logger.
*
* See \c basic_logger class template for a more detailed description.
*/
class logger_mt :
public basic_composite_logger< char, logger_mt, multi_thread_model< boost::log::aux::light_rw_mutex >, features< > >
{
BOOST_LOG_FORWARD_LOGGER_MEMBERS(logger_mt)
};
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif // BOOST_LOG_USE_CHAR
#ifdef BOOST_LOG_USE_WCHAR_T
/*!
* \brief Wide-char logger. Functionally equivalent to \c basic_logger.
*
* See \c basic_logger class template for a more detailed description.
*/
class wlogger :
public basic_composite_logger< wchar_t, wlogger, single_thread_model, features< > >
{
BOOST_LOG_FORWARD_LOGGER_MEMBERS(wlogger)
};
#if !defined(BOOST_LOG_NO_THREADS)
/*!
* \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_logger.
*
* See \c basic_logger class template for a more detailed description.
*/
class wlogger_mt :
public basic_composite_logger< wchar_t, wlogger_mt, multi_thread_model< boost::log::aux::light_rw_mutex >, features< > >
{
BOOST_LOG_FORWARD_LOGGER_MEMBERS(wlogger_mt)
};
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif // BOOST_LOG_USE_WCHAR_T
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_LOGGER_HPP_INCLUDED_
@@ -0,0 +1,583 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file record_ostream.hpp
* \author Andrey Semashev
* \date 09.03.2009
*
* This header contains a wrapper class around a logging record that allows to compose the
* record message with a streaming expression.
*/
#ifndef BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
#include <string>
#include <iosfwd>
#include <ostream>
#include <boost/assert.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/core/addressof.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/native_typeof.hpp>
#include <boost/log/detail/unhandled_exception_count.hpp>
#include <boost/log/core/record.hpp>
#include <boost/log/utility/unique_identifier_name.hpp>
#include <boost/utility/explicit_operator_bool.hpp>
#include <boost/log/utility/formatting_ostream.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
template< typename CharT >
class basic_record_ostream;
namespace aux {
template< typename StreamT, typename T, bool ByValueV, typename R >
struct enable_record_ostream_generic_operator {};
template< typename CharT, typename T, typename R >
struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T, false, R > :
public boost::disable_if_c< boost::is_scalar< typename boost::remove_cv< T >::type >::value, R >
{
};
template< typename CharT, typename T, typename R >
struct enable_record_ostream_generic_operator< basic_record_ostream< CharT >, T, true, R > :
public boost::enable_if_c< boost::is_enum< typename boost::remove_cv< T >::type >::value, R >
{
};
} // namespace aux
/*!
* \brief Logging record adapter with a streaming capability
*
* This class allows to compose the logging record message by streaming operations. It
* aggregates the log record and provides the standard output stream interface.
*/
template< typename CharT >
class basic_record_ostream :
public basic_formatting_ostream< CharT >
{
//! Self type
typedef basic_record_ostream< CharT > this_type;
//! Base stream class
typedef basic_formatting_ostream< CharT > base_type;
public:
//! Character type
typedef CharT char_type;
//! String type to be used as a message text holder
typedef std::basic_string< char_type > string_type;
//! Stream type
typedef std::basic_ostream< char_type > stream_type;
//! Character traits
typedef typename base_type::traits_type traits_type;
private:
//! Log record
record* m_record;
public:
/*!
* Default constructor. Creates an empty record that is equivalent to the invalid record handle.
* The stream capability is not available after construction.
*
* \post <tt>!*this == true</tt>
*/
basic_record_ostream() BOOST_NOEXCEPT : m_record(NULL) {}
/*!
* Constructor from a record object. Attaches to the provided record.
*
* \pre <tt>!!rec == true</tt>
* \post <tt>&this->get_record() == &rec</tt>
* \param rec The record handle being attached to
*/
explicit basic_record_ostream(record& rec)
{
BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record");
m_record = &rec;
init_stream();
}
/*!
* Destructor. Destroys the record, releases any sinks and attribute values that were involved in processing this record.
*/
~basic_record_ostream() BOOST_NOEXCEPT
{
detach_from_record();
}
/*!
* Conversion to an unspecified boolean type
*
* \return \c true, if stream is valid and ready for formatting, \c false, if the stream is not valid. The latter also applies to
* the case when the stream is not attached to a log record.
*/
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
/*!
* Inverted conversion to an unspecified boolean type
*
* \return \c false, if stream is valid and ready for formatting, \c true, if the stream is not valid. The latter also applies to
* the case when the stream is not attached to a log record.
*/
bool operator! () const BOOST_NOEXCEPT
{
return (!m_record || base_type::fail());
}
/*!
* Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record
*
* \return The aggregated record object
*/
record& get_record()
{
BOOST_ASSERT(m_record != NULL);
this->flush();
return *m_record;
}
/*!
* Flushes internal buffers to complete all pending formatting operations and returns the aggregated log record
*
* \return The aggregated record object
*/
record const& get_record() const
{
BOOST_ASSERT(m_record != NULL);
const_cast< this_type* >(this)->flush();
return *m_record;
}
/*!
* If the stream is attached to a log record, flushes internal buffers to complete all pending formatting operations.
* Then reattaches the stream to another log record.
*
* \param rec New log record to attach to
*/
void attach_record(record& rec)
{
BOOST_ASSERT_MSG(!!rec, "Boost.Log: basic_record_ostream should only be attached to a valid record");
detach_from_record();
m_record = &rec;
init_stream();
}
//! The function resets the stream into a detached (default initialized) state
BOOST_LOG_API void detach_from_record() BOOST_NOEXCEPT;
basic_record_ostream& operator<< (typename base_type::ios_base_manip manip)
{
static_cast< base_type& >(*this) << manip;
return *this;
}
basic_record_ostream& operator<< (typename base_type::basic_ios_manip manip)
{
static_cast< base_type& >(*this) << manip;
return *this;
}
basic_record_ostream& operator<< (typename base_type::stream_manip manip)
{
static_cast< base_type& >(*this) << manip;
return *this;
}
basic_record_ostream& operator<< (char c)
{
static_cast< base_type& >(*this) << c;
return *this;
}
basic_record_ostream& operator<< (const char* p)
{
static_cast< base_type& >(*this) << p;
return *this;
}
// When no native character type is supported, the following overloads are disabled as they have ambiguous meaning.
// Use basic_string_view or basic_string to explicitly indicate that the data is a string.
#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
basic_record_ostream& operator<< (wchar_t c)
{
static_cast< base_type& >(*this) << c;
return *this;
}
basic_record_ostream& operator<< (const wchar_t* p)
{
static_cast< base_type& >(*this) << p;
return *this;
}
#endif
#if !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS)
#if !defined(BOOST_NO_CXX11_CHAR16_T)
basic_record_ostream& operator<< (char16_t c)
{
static_cast< base_type& >(*this) << c;
return *this;
}
basic_record_ostream& operator<< (const char16_t* p)
{
static_cast< base_type& >(*this) << p;
return *this;
}
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
basic_record_ostream& operator<< (char32_t c)
{
static_cast< base_type& >(*this) << c;
return *this;
}
basic_record_ostream& operator<< (const char32_t* p)
{
static_cast< base_type& >(*this) << p;
return *this;
}
#endif
#endif
basic_record_ostream& operator<< (bool value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (signed char value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (unsigned char value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (short value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (unsigned short value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (int value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (unsigned int value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (long value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (unsigned long value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
#if !defined(BOOST_NO_LONG_LONG)
basic_record_ostream& operator<< (long long value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (unsigned long long value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
#endif
basic_record_ostream& operator<< (float value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (double value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (long double value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (const void* value)
{
static_cast< base_type& >(*this) << value;
return *this;
}
basic_record_ostream& operator<< (std::basic_streambuf< char_type, traits_type >* buf)
{
static_cast< base_type& >(*this) << buf;
return *this;
}
private:
//! The function initializes the stream and the stream buffer
BOOST_LOG_API void init_stream();
// Copy and assignment are closed
BOOST_DELETED_FUNCTION(basic_record_ostream(basic_record_ostream const&))
BOOST_DELETED_FUNCTION(basic_record_ostream& operator= (basic_record_ostream const&))
};
#ifdef BOOST_LOG_USE_CHAR
typedef basic_record_ostream< char > record_ostream; //!< Convenience typedef for narrow-character logging
#endif
#ifdef BOOST_LOG_USE_WCHAR_T
typedef basic_record_ostream< wchar_t > wrecord_ostream; //!< Convenience typedef for wide-character logging
#endif
// Implementation note: these operators below should be the least attractive for the compiler
// so that user's overloads are chosen, when present. We use function template partial ordering for this purpose.
// We also don't use perfect forwarding for the right hand argument because in ths case the generic overload
// would be more preferred than the typical one written by users:
//
// record_ostream& operator<< (record_ostream& strm, my_type const& arg);
//
// This is because my_type rvalues require adding const to the type, which counts as a conversion that is not required
// if there is a perfect forwarding overload.
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, true, StreamT& >::type
operator<< (StreamT& strm, T value)
{
typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
static_cast< formatting_ostream_type& >(strm) << value;
return strm;
}
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
operator<< (StreamT& strm, T const& value)
{
typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
static_cast< formatting_ostream_type& >(strm) << value;
return strm;
}
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
operator<< (StreamT& strm, T& value)
{
typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
static_cast< formatting_ostream_type& >(strm) << value;
return strm;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, true, StreamT& >::type
operator<< (StreamT&& strm, T value)
{
typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
static_cast< formatting_ostream_type& >(strm) << value;
return strm;
}
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
operator<< (StreamT&& strm, T const& value)
{
typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
static_cast< formatting_ostream_type& >(strm) << value;
return strm;
}
template< typename StreamT, typename T >
inline typename boost::log::aux::enable_record_ostream_generic_operator< StreamT, T, false, StreamT& >::type
operator<< (StreamT&& strm, T& value)
{
typedef basic_formatting_ostream< typename StreamT::char_type > formatting_ostream_type;
static_cast< formatting_ostream_type& >(strm) << value;
return strm;
}
#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
namespace aux {
//! Internal class that provides formatting streams for record pumps
template< typename CharT >
struct stream_provider
{
//! Character type
typedef CharT char_type;
//! Formatting stream compound
struct stream_compound
{
stream_compound* next;
//! Log record stream adapter
basic_record_ostream< char_type > stream;
//! Initializing constructor
explicit stream_compound(record& rec) : next(NULL), stream(rec) {}
};
//! The method returns an allocated stream compound
BOOST_LOG_API static stream_compound* allocate_compound(record& rec);
//! The method releases a compound
BOOST_LOG_API static void release_compound(stream_compound* compound) BOOST_NOEXCEPT;
// Non-constructible, non-copyable, non-assignable
BOOST_DELETED_FUNCTION(stream_provider())
BOOST_DELETED_FUNCTION(stream_provider(stream_provider const&))
BOOST_DELETED_FUNCTION(stream_provider& operator= (stream_provider const&))
};
/*!
* \brief Logging record pump implementation
*
* The pump is used to format the logging record message text and then
* push it to the logging core. It is constructed on each attempt to write
* a log record and destroyed afterwards.
*
* The pump class template is instantiated on the logger type.
*/
template< typename LoggerT >
class record_pump
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(record_pump)
private:
//! Logger type
typedef LoggerT logger_type;
//! Character type
typedef typename logger_type::char_type char_type;
//! Stream compound provider
typedef stream_provider< char_type > stream_provider_type;
//! Stream compound type
typedef typename stream_provider_type::stream_compound stream_compound;
//! Stream compound release guard
class auto_release;
friend class auto_release;
class auto_release
{
stream_compound* m_pCompound;
public:
explicit auto_release(stream_compound* p) BOOST_NOEXCEPT : m_pCompound(p) {}
~auto_release() BOOST_NOEXCEPT { stream_provider_type::release_compound(m_pCompound); }
};
protected:
//! A reference to the logger
logger_type* m_pLogger;
//! Stream compound
stream_compound* m_pStreamCompound;
//! Exception state
const unsigned int m_ExceptionCount;
public:
//! Constructor
explicit record_pump(logger_type& lg, record& rec) :
m_pLogger(boost::addressof(lg)),
m_pStreamCompound(stream_provider_type::allocate_compound(rec)),
m_ExceptionCount(unhandled_exception_count())
{
}
//! Move constructor
record_pump(BOOST_RV_REF(record_pump) that) BOOST_NOEXCEPT :
m_pLogger(that.m_pLogger),
m_pStreamCompound(that.m_pStreamCompound),
m_ExceptionCount(that.m_ExceptionCount)
{
that.m_pLogger = 0;
that.m_pStreamCompound = 0;
}
//! Destructor. Pushes the composed message to log.
~record_pump() BOOST_NOEXCEPT_IF(false)
{
if (m_pLogger)
{
auto_release cleanup(m_pStreamCompound); // destructor doesn't throw
// Only push the record if no exception has been thrown in the streaming expression (if possible)
if (m_ExceptionCount >= unhandled_exception_count())
m_pLogger->push_record(boost::move(m_pStreamCompound->stream.get_record()));
}
}
//! Returns the stream to be used for message text formatting
basic_record_ostream< char_type >& stream() const BOOST_NOEXCEPT
{
BOOST_ASSERT(m_pStreamCompound != 0);
return m_pStreamCompound->stream;
}
};
template< typename LoggerT >
BOOST_FORCEINLINE record_pump< LoggerT > make_record_pump(LoggerT& lg, record& rec)
{
return record_pump< LoggerT >(lg, rec);
}
} // namespace aux
#ifndef BOOST_LOG_DOXYGEN_PASS
#define BOOST_LOG_STREAM_INTERNAL(logger, rec_var)\
for (::boost::log::record rec_var = (logger).open_record(); !!rec_var;)\
::boost::log::aux::make_record_pump((logger), rec_var).stream()
#define BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, rec_var, params_seq)\
for (::boost::log::record rec_var = (logger).open_record((BOOST_PP_SEQ_ENUM(params_seq))); !!rec_var;)\
::boost::log::aux::make_record_pump((logger), rec_var).stream()
#endif // BOOST_LOG_DOXYGEN_PASS
//! The macro writes a record to the log
#define BOOST_LOG_STREAM(logger)\
BOOST_LOG_STREAM_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_))
//! The macro writes a record to the log and allows to pass additional named arguments to the logger
#define BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)\
BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL(logger, BOOST_LOG_UNIQUE_IDENTIFIER_NAME(_boost_log_record_), params_seq)
#ifndef BOOST_LOG_NO_SHORTHAND_NAMES
//! An equivalent to BOOST_LOG_STREAM(logger)
#define BOOST_LOG(logger) BOOST_LOG_STREAM(logger)
//! An equivalent to BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)
#define BOOST_LOG_WITH_PARAMS(logger, params_seq) BOOST_LOG_STREAM_WITH_PARAMS(logger, params_seq)
#endif // BOOST_LOG_NO_SHORTHAND_NAMES
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_RECORD_OSTREAM_HPP_INCLUDED_
@@ -0,0 +1,309 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file severity_channel_logger.hpp
* \author Andrey Semashev
* \date 28.02.2008
*
* The header contains implementation of a logger with severity level and channel support.
*/
#ifndef BOOST_LOG_SOURCES_SEVERITY_CHANNEL_LOGGER_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_SEVERITY_CHANNEL_LOGGER_HPP_INCLUDED_
#include <string>
#include <boost/log/detail/config.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/detail/light_rw_mutex.hpp>
#endif // !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/sources/features.hpp>
#include <boost/log/sources/basic_logger.hpp>
#include <boost/log/sources/threading_models.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/sources/channel_feature.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
#ifndef BOOST_LOG_DOXYGEN_PASS
#ifdef BOOST_LOG_USE_CHAR
//! Narrow-char logger with severity level and channel support
template< typename LevelT = int, typename ChannelT = std::string >
class severity_channel_logger :
public basic_composite_logger<
char,
severity_channel_logger< LevelT, ChannelT >,
single_thread_model,
features<
severity< LevelT >,
channel< ChannelT >
>
>
{
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_channel_logger)
};
#if !defined(BOOST_LOG_NO_THREADS)
//! Narrow-char thread-safe logger with severity level and channel support
template< typename LevelT = int, typename ChannelT = std::string >
class severity_channel_logger_mt :
public basic_composite_logger<
char,
severity_channel_logger_mt< LevelT, ChannelT >,
multi_thread_model< boost::log::aux::light_rw_mutex >,
features<
severity< LevelT >,
channel< ChannelT >
>
>
{
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_channel_logger_mt)
};
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif // BOOST_LOG_USE_CHAR
#ifdef BOOST_LOG_USE_WCHAR_T
//! Wide-char logger with severity level and channel support
template< typename LevelT = int, typename ChannelT = std::wstring >
class wseverity_channel_logger :
public basic_composite_logger<
wchar_t,
wseverity_channel_logger< LevelT, ChannelT >,
single_thread_model,
features<
severity< LevelT >,
channel< ChannelT >
>
>
{
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_channel_logger)
};
#if !defined(BOOST_LOG_NO_THREADS)
//! Wide-char thread-safe logger with severity level and channel support
template< typename LevelT = int, typename ChannelT = std::wstring >
class wseverity_channel_logger_mt :
public basic_composite_logger<
wchar_t,
wseverity_channel_logger_mt< LevelT, ChannelT >,
multi_thread_model< boost::log::aux::light_rw_mutex >,
features<
severity< LevelT >,
channel< ChannelT >
>
>
{
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_channel_logger_mt)
};
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif // BOOST_LOG_USE_WCHAR_T
#else // BOOST_LOG_DOXYGEN_PASS
/*!
* \brief Narrow-char logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger.
*
* See \c severity and \c channel class templates for a more detailed description
*/
template< typename LevelT = int, typename ChannelT = std::string >
class severity_channel_logger :
public basic_composite_logger<
char,
severity_channel_logger< LevelT, ChannelT >,
single_thread_model,
features<
severity< LevelT >,
channel< ChannelT >
>
>
{
public:
/*!
* Default constructor
*/
severity_channel_logger();
/*!
* Copy constructor
*/
severity_channel_logger(severity_channel_logger const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit severity_channel_logger(ArgsT... const& args);
/*!
* Assignment operator
*/
severity_channel_logger& operator= (severity_channel_logger const& that)
/*!
* Swaps two loggers
*/
void swap(severity_channel_logger& that);
};
/*!
* \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger.
*
* See \c severity and \c channel class templates for a more detailed description
*/
template< typename LevelT = int, typename ChannelT = std::string >
class severity_channel_logger_mt :
public basic_composite_logger<
char,
severity_channel_logger_mt< LevelT, ChannelT >,
multi_thread_model< implementation_defined >,
features<
severity< LevelT >,
channel< ChannelT >
>
>
{
public:
/*!
* Default constructor
*/
severity_channel_logger_mt();
/*!
* Copy constructor
*/
severity_channel_logger_mt(severity_channel_logger_mt const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit severity_channel_logger_mt(ArgsT... const& args);
/*!
* Assignment operator
*/
severity_channel_logger_mt& operator= (severity_channel_logger_mt const& that)
/*!
* Swaps two loggers
*/
void swap(severity_channel_logger_mt& that);
};
/*!
* \brief Wide-char logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger.
*
* See \c severity and \c channel class templates for a more detailed description
*/
template< typename LevelT = int, typename ChannelT = std::wstring >
class wseverity_channel_logger :
public basic_composite_logger<
wchar_t,
wseverity_channel_logger< LevelT, ChannelT >,
single_thread_model,
features<
severity< LevelT >,
channel< ChannelT >
>
>
{
public:
/*!
* Default constructor
*/
wseverity_channel_logger();
/*!
* Copy constructor
*/
wseverity_channel_logger(wseverity_channel_logger const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit wseverity_channel_logger(ArgsT... const& args);
/*!
* Assignment operator
*/
wseverity_channel_logger& operator= (wseverity_channel_logger const& that)
/*!
* Swaps two loggers
*/
void swap(wseverity_channel_logger& that);
};
/*!
* \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_severity_logger and \c basic_channel_logger.
*
* See \c severity and \c channel class templates for a more detailed description
*/
template< typename LevelT = int, typename ChannelT = std::wstring >
class wseverity_channel_logger_mt :
public basic_composite_logger<
wchar_t,
wseverity_channel_logger_mt< LevelT, ChannelT >,
multi_thread_model< implementation_defined >,
features<
severity< LevelT >,
channel< ChannelT >
>
>
{
public:
/*!
* Default constructor
*/
wseverity_channel_logger_mt();
/*!
* Copy constructor
*/
wseverity_channel_logger_mt(wseverity_channel_logger_mt const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit wseverity_channel_logger_mt(ArgsT... const& args);
/*!
* Assignment operator
*/
wseverity_channel_logger_mt& operator= (wseverity_channel_logger_mt const& that)
/*!
* Swaps two loggers
*/
void swap(wseverity_channel_logger_mt& that);
};
#endif // BOOST_LOG_DOXYGEN_PASS
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
//! The macro allows to put a record with a specific channel name into log
#define BOOST_LOG_STREAM_CHANNEL_SEV(logger, chan, lvl)\
BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::channel = (chan))(::boost::log::keywords::severity = (lvl)))
#ifndef BOOST_LOG_NO_SHORTHAND_NAMES
//! An equivalent to BOOST_LOG_STREAM_CHANNEL_SEV(logger, chan, lvl)
#define BOOST_LOG_CHANNEL_SEV(logger, chan, lvl) BOOST_LOG_STREAM_CHANNEL_SEV(logger, chan, lvl)
#endif // BOOST_LOG_NO_SHORTHAND_NAMES
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_SEVERITY_CHANNEL_LOGGER_HPP_INCLUDED_
@@ -0,0 +1,310 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file severity_feature.hpp
* \author Andrey Semashev
* \date 08.03.2007
*
* The header contains implementation of a severity level support feature.
*/
#ifndef BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include <boost/move/core.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/locks.hpp>
#include <boost/log/detail/default_attribute_names.hpp>
#include <boost/log/attributes/attribute.hpp>
#include <boost/log/attributes/attribute_cast.hpp>
#include <boost/log/attributes/attribute_value_impl.hpp>
#include <boost/log/utility/strictest_lock.hpp>
#include <boost/log/utility/type_dispatch/type_dispatcher.hpp>
#include <boost/log/keywords/severity.hpp>
#include <boost/log/core/record.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
namespace aux {
//! The method returns the storage for severity level for the current thread
BOOST_LOG_API uintmax_t& get_severity_level();
//! Severity level attribute implementation
template< typename LevelT >
class severity_level :
public attribute
{
typedef severity_level this_type;
BOOST_COPYABLE_AND_MOVABLE(this_type)
public:
//! Stored level type
typedef LevelT value_type;
BOOST_STATIC_ASSERT_MSG(sizeof(value_type) <= sizeof(uintmax_t), "Boost.Log: Unsupported severity level type, the severity level must fit into uintmax_t");
protected:
//! Factory implementation
class BOOST_SYMBOL_VISIBLE impl :
public attribute_value::impl
{
public:
//! The method dispatches the value to the given object
bool dispatch(type_dispatcher& dispatcher)
{
type_dispatcher::callback< value_type > callback = dispatcher.get_callback< value_type >();
if (callback)
{
callback(reinterpret_cast< value_type const& >(get_severity_level()));
return true;
}
else
return false;
}
//! The method is called when the attribute value is passed to another thread
intrusive_ptr< attribute_value::impl > detach_from_thread()
{
#if !defined(BOOST_LOG_NO_THREADS)
return new attributes::attribute_value_impl< value_type >(
reinterpret_cast< value_type const& >(get_severity_level()));
#else
// With multithreading disabled we may safely return this here. This method will not be called anyway.
return this;
#endif
}
};
public:
//! Default constructor
severity_level() : attribute(new impl())
{
}
//! Copy constructor
severity_level(severity_level const& that) : attribute(static_cast< attribute const& >(that))
{
}
//! Move constructor
severity_level(BOOST_RV_REF(severity_level) that) : attribute(boost::move(static_cast< attribute& >(that)))
{
}
//! Constructor for casting support
explicit severity_level(attributes::cast_source const& source) :
attribute(source.as< impl >())
{
}
/*!
* Copy assignment
*/
severity_level& operator= (BOOST_COPY_ASSIGN_REF(severity_level) that)
{
attribute::operator= (that);
return *this;
}
/*!
* Move assignment
*/
severity_level& operator= (BOOST_RV_REF(severity_level) that)
{
this->swap(that);
return *this;
}
//! The method sets the actual level
void set_value(value_type level)
{
reinterpret_cast< value_type& >(get_severity_level()) = level;
}
};
} // namespace aux
/*!
* \brief Severity level feature implementation
*/
template< typename BaseT, typename LevelT = int >
class basic_severity_logger :
public BaseT
{
//! Base type
typedef BaseT base_type;
typedef basic_severity_logger this_type;
BOOST_COPYABLE_AND_MOVABLE_ALT(this_type)
public:
//! Character type
typedef typename base_type::char_type char_type;
//! Final type
typedef typename base_type::final_type final_type;
//! Threading model being used
typedef typename base_type::threading_model threading_model;
//! Severity level type
typedef LevelT severity_level;
//! Severity attribute type
typedef aux::severity_level< severity_level > severity_attribute;
#if defined(BOOST_LOG_DOXYGEN_PASS)
//! Lock requirement for the \c open_record_unlocked method
typedef typename strictest_lock<
typename base_type::open_record_lock,
no_lock< threading_model >
>::type open_record_lock;
#endif // defined(BOOST_LOG_DOXYGEN_PASS)
//! Lock requirement for the \c swap_unlocked method
typedef typename strictest_lock<
typename base_type::swap_lock,
#ifndef BOOST_LOG_NO_THREADS
boost::log::aux::exclusive_lock_guard< threading_model >
#else
no_lock< threading_model >
#endif // !defined(BOOST_LOG_NO_THREADS)
>::type swap_lock;
private:
//! Default severity
severity_level m_DefaultSeverity;
//! Severity attribute
severity_attribute m_SeverityAttr;
public:
/*!
* Default constructor. The constructed logger will have a severity attribute registered.
* The default level for log records will be 0.
*/
basic_severity_logger() :
base_type(),
m_DefaultSeverity(static_cast< severity_level >(0))
{
base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr);
}
/*!
* Copy constructor
*/
basic_severity_logger(basic_severity_logger const& that) :
base_type(static_cast< base_type const& >(that)),
m_DefaultSeverity(that.m_DefaultSeverity),
m_SeverityAttr(that.m_SeverityAttr)
{
base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr;
}
/*!
* Move constructor
*/
basic_severity_logger(BOOST_RV_REF(basic_severity_logger) that) :
base_type(boost::move(static_cast< base_type& >(that))),
m_DefaultSeverity(boost::move(that.m_DefaultSeverity)),
m_SeverityAttr(boost::move(that.m_SeverityAttr))
{
base_type::attributes()[boost::log::aux::default_attribute_names::severity()] = m_SeverityAttr;
}
/*!
* Constructor with named arguments. Allows to setup the default level for log records.
*
* \param args A set of named arguments. The following arguments are supported:
* \li \c severity - default severity value
*/
template< typename ArgsT >
explicit basic_severity_logger(ArgsT const& args) :
base_type(args),
m_DefaultSeverity(args[keywords::severity | severity_level()])
{
base_type::add_attribute_unlocked(boost::log::aux::default_attribute_names::severity(), m_SeverityAttr);
}
/*!
* Default severity value getter
*/
severity_level default_severity() const { return m_DefaultSeverity; }
protected:
/*!
* Severity attribute accessor
*/
severity_attribute const& get_severity_attribute() const { return m_SeverityAttr; }
/*!
* Unlocked \c open_record
*/
template< typename ArgsT >
record open_record_unlocked(ArgsT const& args)
{
m_SeverityAttr.set_value(args[keywords::severity | m_DefaultSeverity]);
return base_type::open_record_unlocked(args);
}
//! Unlocked \c swap
void swap_unlocked(basic_severity_logger& that)
{
base_type::swap_unlocked(static_cast< base_type& >(that));
severity_level t = m_DefaultSeverity;
m_DefaultSeverity = that.m_DefaultSeverity;
that.m_DefaultSeverity = t;
m_SeverityAttr.swap(that.m_SeverityAttr);
}
};
/*!
* \brief Severity level support feature
*
* The logger with this feature registers a special attribute with an integral value type on construction.
* This attribute will provide severity level for each log record being made through the logger.
* The severity level can be omitted on logging record construction, in which case the default
* level will be used. The default level can also be customized by passing it to the logger constructor.
*
* The type of the severity level attribute can be specified as a template parameter for the feature
* template. By default, \c int will be used.
*/
template< typename LevelT = int >
struct severity
{
template< typename BaseT >
struct apply
{
typedef basic_severity_logger<
BaseT,
LevelT
> type;
};
};
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
//! The macro allows to put a record with a specific severity level into log
#define BOOST_LOG_STREAM_SEV(logger, lvl)\
BOOST_LOG_STREAM_WITH_PARAMS((logger), (::boost::log::keywords::severity = (lvl)))
#ifndef BOOST_LOG_NO_SHORTHAND_NAMES
//! An equivalent to BOOST_LOG_STREAM_SEV(logger, lvl)
#define BOOST_LOG_SEV(logger, lvl) BOOST_LOG_STREAM_SEV(logger, lvl)
#endif // BOOST_LOG_NO_SHORTHAND_NAMES
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_SEVERITY_FEATURE_HPP_INCLUDED_
@@ -0,0 +1,325 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file severity_logger.hpp
* \author Andrey Semashev
* \date 08.03.2007
*
* The header contains implementation of a logger with severity level support.
*/
#ifndef BOOST_LOG_SOURCES_SEVERITY_LOGGER_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_SEVERITY_LOGGER_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/detail/light_rw_mutex.hpp>
#endif // !defined(BOOST_LOG_NO_THREADS)
#include <boost/log/sources/features.hpp>
#include <boost/log/sources/basic_logger.hpp>
#include <boost/log/sources/threading_models.hpp>
#include <boost/log/sources/severity_feature.hpp>
#include <boost/log/keywords/severity.hpp>
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
#ifndef BOOST_LOG_DOXYGEN_PASS
#ifdef BOOST_LOG_USE_CHAR
//! Narrow-char logger with severity level support
template< typename LevelT = int >
class severity_logger :
public basic_composite_logger<
char,
severity_logger< LevelT >,
single_thread_model,
features< severity< LevelT > >
>
{
typedef typename severity_logger::logger_base base_type;
public:
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_logger)
explicit severity_logger(LevelT level) : base_type(keywords::severity = level)
{
}
};
#if !defined(BOOST_LOG_NO_THREADS)
//! Narrow-char thread-safe logger with severity level support
template< typename LevelT = int >
class severity_logger_mt :
public basic_composite_logger<
char,
severity_logger_mt< LevelT >,
multi_thread_model< boost::log::aux::light_rw_mutex >,
features< severity< LevelT > >
>
{
typedef typename severity_logger_mt::logger_base base_type;
public:
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(severity_logger_mt)
explicit severity_logger_mt(LevelT level) : base_type(keywords::severity = level)
{
}
};
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif
#ifdef BOOST_LOG_USE_WCHAR_T
//! Wide-char logger with severity level support
template< typename LevelT = int >
class wseverity_logger :
public basic_composite_logger<
wchar_t,
wseverity_logger< LevelT >,
single_thread_model,
features< severity< LevelT > >
>
{
typedef typename wseverity_logger::logger_base base_type;
public:
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_logger)
explicit wseverity_logger(LevelT level) : base_type(keywords::severity = level)
{
}
};
#if !defined(BOOST_LOG_NO_THREADS)
//! Wide-char thread-safe logger with severity level support
template< typename LevelT = int >
class wseverity_logger_mt :
public basic_composite_logger<
wchar_t,
wseverity_logger_mt< LevelT >,
multi_thread_model< boost::log::aux::light_rw_mutex >,
features< severity< LevelT > >
>
{
typedef typename wseverity_logger_mt::logger_base base_type;
public:
BOOST_LOG_FORWARD_LOGGER_MEMBERS_TEMPLATE(wseverity_logger_mt)
explicit wseverity_logger_mt(LevelT level) : base_type(keywords::severity = level)
{
}
};
#endif // !defined(BOOST_LOG_NO_THREADS)
#endif
#else // BOOST_LOG_DOXYGEN_PASS
/*!
* \brief Narrow-char logger. Functionally equivalent to \c basic_severity_logger.
*
* See \c severity class template for a more detailed description
*/
template< typename LevelT = int >
class severity_logger :
public basic_composite_logger<
char,
severity_logger< LevelT >,
single_thread_model,
features< severity< LevelT > >
>
{
public:
/*!
* Default constructor
*/
severity_logger();
/*!
* Copy constructor
*/
severity_logger(severity_logger const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit severity_logger(ArgsT... const& args);
/*!
* The constructor creates the logger with the specified default severity level
*
* \param level The default severity level
*/
explicit severity_logger(LevelT level);
/*!
* Assignment operator
*/
severity_logger& operator= (severity_logger const& that)
/*!
* Swaps two loggers
*/
void swap(severity_logger& that);
};
/*!
* \brief Narrow-char thread-safe logger. Functionally equivalent to \c basic_severity_logger.
*
* See \c severity class template for a more detailed description
*/
template< typename LevelT = int >
class severity_logger_mt :
public basic_composite_logger<
char,
severity_logger_mt< LevelT >,
multi_thread_model< implementation_defined >,
features< severity< LevelT > >
>
{
public:
/*!
* Default constructor
*/
severity_logger_mt();
/*!
* Copy constructor
*/
severity_logger_mt(severity_logger_mt const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit severity_logger_mt(ArgsT... const& args);
/*!
* The constructor creates the logger with the specified default severity level
*
* \param level The default severity level
*/
explicit severity_logger_mt(LevelT level);
/*!
* Assignment operator
*/
severity_logger_mt& operator= (severity_logger_mt const& that)
/*!
* Swaps two loggers
*/
void swap(severity_logger_mt& that);
};
/*!
* \brief Wide-char logger. Functionally equivalent to \c basic_severity_logger.
*
* See \c severity class template for a more detailed description
*/
template< typename LevelT = int >
class wseverity_logger :
public basic_composite_logger<
wchar_t,
wseverity_logger< LevelT >,
single_thread_model,
features< severity< LevelT > >
>
{
public:
/*!
* Default constructor
*/
wseverity_logger();
/*!
* Copy constructor
*/
wseverity_logger(wseverity_logger const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit wseverity_logger(ArgsT... const& args);
/*!
* The constructor creates the logger with the specified default severity level
*
* \param level The default severity level
*/
explicit wseverity_logger(LevelT level);
/*!
* Assignment operator
*/
wseverity_logger& operator= (wseverity_logger const& that)
/*!
* Swaps two loggers
*/
void swap(wseverity_logger& that);
};
/*!
* \brief Wide-char thread-safe logger. Functionally equivalent to \c basic_severity_logger.
*
* See \c severity class template for a more detailed description
*/
template< typename LevelT = int >
class wseverity_logger_mt :
public basic_composite_logger<
wchar_t,
wseverity_logger_mt< LevelT >,
multi_thread_model< implementation_defined >,
features< severity< LevelT > >
>
{
public:
/*!
* Default constructor
*/
wseverity_logger_mt();
/*!
* Copy constructor
*/
wseverity_logger_mt(wseverity_logger_mt const& that);
/*!
* Constructor with named arguments
*/
template< typename... ArgsT >
explicit wseverity_logger_mt(ArgsT... const& args);
/*!
* The constructor creates the logger with the specified default severity level
*
* \param level The default severity level
*/
explicit wseverity_logger_mt(LevelT level);
/*!
* Assignment operator
*/
wseverity_logger_mt& operator= (wseverity_logger_mt const& that)
/*!
* Swaps two loggers
*/
void swap(wseverity_logger_mt& that);
};
#endif // BOOST_LOG_DOXYGEN_PASS
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_SEVERITY_LOGGER_HPP_INCLUDED_
@@ -0,0 +1,125 @@
/*
* Copyright Andrey Semashev 2007 - 2015.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file sources/threading_models.hpp
* \author Andrey Semashev
* \date 04.10.2008
*
* The header contains definition of threading models that can be used in loggers.
* The header also provides a number of tags that can be used to express lock requirements
* on a function callee.
*/
#ifndef BOOST_LOG_SOURCES_THREADING_MODELS_HPP_INCLUDED_
#define BOOST_LOG_SOURCES_THREADING_MODELS_HPP_INCLUDED_
#include <boost/log/detail/config.hpp>
#include <boost/log/detail/locks.hpp> // is_mutex_type
#if !defined(BOOST_LOG_NO_THREADS)
#include <boost/mpl/bool.hpp>
#endif
#include <boost/log/detail/header.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
namespace boost {
BOOST_LOG_OPEN_NAMESPACE
namespace sources {
//! Single thread locking model
struct single_thread_model
{
// We provide methods for the most advanced locking concept: UpgradeLockable
void lock_shared() const {}
bool try_lock_shared() const { return true; }
template< typename TimeT >
bool timed_lock_shared(TimeT const&) const { return true; }
void unlock_shared() const {}
void lock() const {}
bool try_lock() const { return true; }
template< typename TimeT >
bool timed_lock(TimeT const&) const { return true; }
void unlock() const {}
void lock_upgrade() const {}
bool try_lock_upgrade() const { return true; }
template< typename TimeT >
bool timed_lock_upgrade(TimeT const&) const { return true; }
void unlock_upgrade() const {}
void unlock_upgrade_and_lock() const {}
void unlock_and_lock_upgrade() const {}
void unlock_and_lock_shared() const {}
void unlock_upgrade_and_lock_shared() const {}
void swap(single_thread_model&) {}
};
#if !defined(BOOST_LOG_NO_THREADS)
//! Multi-thread locking model with maximum locking capabilities
template< typename MutexT >
struct multi_thread_model
{
multi_thread_model() {}
multi_thread_model(multi_thread_model const&) {}
multi_thread_model& operator= (multi_thread_model const&) { return *this; }
void lock_shared() const { m_Mutex.lock_shared(); }
bool try_lock_shared() const { return m_Mutex.try_lock_shared(); }
template< typename TimeT >
bool timed_lock_shared(TimeT const& t) const { return m_Mutex.timed_lock_shared(t); }
void unlock_shared() const { m_Mutex.unlock_shared(); }
void lock() const { m_Mutex.lock(); }
bool try_lock() const { return m_Mutex.try_lock(); }
template< typename TimeT >
bool timed_lock(TimeT const& t) const { return m_Mutex.timed_lock(t); }
void unlock() const { m_Mutex.unlock(); }
void lock_upgrade() const { m_Mutex.lock_upgrade(); }
bool try_lock_upgrade() const { return m_Mutex.try_lock_upgrade(); }
template< typename TimeT >
bool timed_lock_upgrade(TimeT const& t) const { return m_Mutex.timed_lock_upgrade(t); }
void unlock_upgrade() const { m_Mutex.unlock_upgrade(); }
void unlock_upgrade_and_lock() const { m_Mutex.unlock_upgrade_and_lock(); }
void unlock_and_lock_upgrade() const { m_Mutex.unlock_and_lock_upgrade(); }
void unlock_and_lock_shared() const { m_Mutex.unlock_and_lock_shared(); }
void unlock_upgrade_and_lock_shared() const { m_Mutex.unlock_upgrade_and_lock_shared(); }
void swap(multi_thread_model&) {}
private:
//! Synchronization primitive
mutable MutexT m_Mutex;
};
#endif // !defined(BOOST_LOG_NO_THREADS)
} // namespace sources
BOOST_LOG_CLOSE_NAMESPACE // namespace log
#if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_LOG_DOXYGEN_PASS)
template< >
struct is_mutex_type< boost::log::sources::single_thread_model > : mpl::true_
{
};
template< typename T >
struct is_mutex_type< boost::log::sources::multi_thread_model< T > > : mpl::true_
{
};
#endif // !defined(BOOST_LOG_NO_THREADS)
} // namespace boost
#include <boost/log/detail/footer.hpp>
#endif // BOOST_LOG_SOURCES_THREADING_MODELS_HPP_INCLUDED_