diff options
author | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
commit | 08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch) | |
tree | 7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/log/detail | |
parent | bb4dd8289b351fae6b55e303f189127a394a1edd (diff) | |
download | boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2 boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip |
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'boost/log/detail')
51 files changed, 7239 insertions, 0 deletions
diff --git a/boost/log/detail/asio_fwd.hpp b/boost/log/detail/asio_fwd.hpp new file mode 100644 index 0000000000..e284c24eed --- /dev/null +++ b/boost/log/detail/asio_fwd.hpp @@ -0,0 +1,43 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 asio_fwd.hpp + * \author Andrey Semashev + * \date 20.04.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + * + * The header provides forward declarations of Boost.ASIO that are required for the user's + * code to compile with Boost.Log. The forward declarations allow to avoid including the major + * part of Boost.ASIO and system headers into user's code. + */ + +#ifndef BOOST_LOG_DETAIL_ASIO_FWD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ASIO_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +namespace asio { + +namespace ip { + +class address; + +} // namespace ip + +} // namespace asio + +} // namespace boost + +#endif // BOOST_LOG_DETAIL_ASIO_FWD_HPP_INCLUDED_ diff --git a/boost/log/detail/attachable_sstream_buf.hpp b/boost/log/detail/attachable_sstream_buf.hpp new file mode 100644 index 0000000000..9b0a05316d --- /dev/null +++ b/boost/log/detail/attachable_sstream_buf.hpp @@ -0,0 +1,172 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 attachable_sstream_buf.hpp + * \author Andrey Semashev + * \date 29.07.2007 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_ +#define BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_ + +#include <memory> +#include <string> +#include <streambuf> +#include <boost/assert.hpp> +#include <boost/utility/addressof.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A streambuf that puts the formatted data to an external string +template< + typename CharT, + typename TraitsT = std::char_traits< CharT >, + typename AllocatorT = std::allocator< CharT > +> +class basic_ostringstreambuf : + public std::basic_streambuf< CharT, TraitsT > +{ + //! Self type + typedef basic_ostringstreambuf< CharT, TraitsT, AllocatorT > this_type; + //! Base type + typedef std::basic_streambuf< CharT, TraitsT > base_type; + + //! Buffer size + enum { buffer_size = 16 }; + +public: + //! Character type + typedef typename base_type::char_type char_type; + //! Traits type + typedef typename base_type::traits_type traits_type; + //! String type + typedef std::basic_string< char_type, traits_type, AllocatorT > string_type; + //! Int type + typedef typename base_type::int_type int_type; + +private: + //! A reference to the string that will be filled + string_type* m_Storage; + //! A buffer used to temporarily store output + char_type m_Buffer[buffer_size]; + +public: + //! Constructor + explicit basic_ostringstreambuf() : m_Storage(0) + { + base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer))); + } + //! Constructor + explicit basic_ostringstreambuf(string_type& storage) : m_Storage(boost::addressof(storage)) + { + base_type::setp(m_Buffer, m_Buffer + (sizeof(m_Buffer) / sizeof(*m_Buffer))); + } + + //! Clears the buffer to the initial state + void clear() + { + char_type* pBase = this->pbase(); + char_type* pPtr = this->pptr(); + if (pBase != pPtr) + this->pbump(static_cast< int >(pBase - pPtr)); + } + + //! Detaches the buffer from the string + void detach() + { + if (m_Storage) + { + this_type::sync(); + m_Storage = 0; + } + } + + //! Attaches the buffer to another string + void attach(string_type& storage) + { + detach(); + m_Storage = boost::addressof(storage); + } + + //! Returns a pointer to the attached string + string_type* storage() const { return m_Storage; } + +protected: + //! Puts all buffered data to the string + int sync() + { + BOOST_ASSERT(m_Storage != 0); + char_type* pBase = this->pbase(); + char_type* pPtr = this->pptr(); + if (pBase != pPtr) + { + m_Storage->append(pBase, pPtr); + this->pbump(static_cast< int >(pBase - pPtr)); + } + return 0; + } + //! Puts an unbuffered character to the string + int_type overflow(int_type c) + { + BOOST_ASSERT(m_Storage != 0); + basic_ostringstreambuf::sync(); + if (!traits_type::eq_int_type(c, traits_type::eof())) + { + m_Storage->push_back(traits_type::to_char_type(c)); + return c; + } + else + return traits_type::not_eof(c); + } + //! Puts a character sequence to the string + std::streamsize xsputn(const char_type* s, std::streamsize n) + { + BOOST_ASSERT(m_Storage != 0); + basic_ostringstreambuf::sync(); + typedef typename string_type::size_type string_size_type; + const string_size_type max_storage_left = + m_Storage->max_size() - m_Storage->size(); + if (static_cast< string_size_type >(n) < max_storage_left) + { + m_Storage->append(s, static_cast< string_size_type >(n)); + return n; + } + else + { + m_Storage->append(s, max_storage_left); + return static_cast< std::streamsize >(max_storage_left); + } + } + + //! Copy constructor (closed) + BOOST_DELETED_FUNCTION(basic_ostringstreambuf(basic_ostringstreambuf const& that)) + //! Assignment (closed) + BOOST_DELETED_FUNCTION(basic_ostringstreambuf& operator= (basic_ostringstreambuf const& that)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_ATTACHABLE_SSTREAM_BUF_HPP_INCLUDED_ diff --git a/boost/log/detail/attr_output_impl.hpp b/boost/log/detail/attr_output_impl.hpp new file mode 100644 index 0000000000..8f00736c5f --- /dev/null +++ b/boost/log/detail/attr_output_impl.hpp @@ -0,0 +1,111 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 attr_output_impl.hpp + * \author Andrey Semashev + * \date 12.08.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_ATTR_OUTPUT_IMPL_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ATTR_OUTPUT_IMPL_HPP_INCLUDED_ + +#include <boost/mpl/is_sequence.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/expressions/attr.hpp> +#include <boost/log/utility/functional/bind_to_log.hpp> +#include <boost/log/detail/attr_output_terminal.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +template< typename LeftT, typename T, typename FallbackPolicyT, typename TagT > +struct make_output_expression +{ + //! Resulting expression + typedef attribute_output_terminal< LeftT, T, FallbackPolicyT, to_log_fun< TagT > > type; + + //! Creates the output expression + template< typename RightT > + static BOOST_FORCEINLINE type make(LeftT const& left, RightT const& right) + { + return type(left, right.get_name(), to_log_fun< TagT >(), right.get_fallback_policy()); + } +}; + +template< typename LeftT, typename RightT, typename ValueT = typename RightT::value_type, bool IsSequenceV = mpl::is_sequence< ValueT >::value > +struct make_output_actor; + +template< template< typename > class ActorT, typename LeftExprT, typename RightT, typename ValueT > +struct make_output_actor< ActorT< LeftExprT >, RightT, ValueT, false > +{ + typedef make_output_expression< + ActorT< LeftExprT >, + ValueT, + typename RightT::fallback_policy, + typename RightT::tag_type + > make_expression; + + typedef ActorT< typename make_expression::type > type; + + static BOOST_FORCEINLINE type make(ActorT< LeftExprT > const& left, RightT const& right) + { + type res = {{ make_expression::make(left, right) }}; + return res; + } +}; + +template< template< typename > class ActorT, typename LeftExprT, typename RightT, typename ValueT > +struct make_output_actor< ActorT< LeftExprT >, RightT, ValueT, true > +{ + typedef attribute_output_terminal< ActorT< LeftExprT >, ValueT, typename RightT::fallback_policy, to_log_fun< typename RightT::tag_type > > expression_type; + + typedef ActorT< expression_type > type; + + static BOOST_FORCEINLINE type make(ActorT< LeftExprT > const& left, RightT const& right) + { + type res = {{ expression_type(left, right.get_name(), to_log_fun< typename RightT::tag_type >(), right.get_fallback_policy()) }}; + return res; + } +}; + +} // namespace aux + +#define BOOST_LOG_AUX_OVERLOAD(left_ref, right_ref)\ + template< typename LeftExprT, typename T, typename FallbackPolicyT, typename TagT >\ + BOOST_FORCEINLINE typename aux::make_output_actor< phoenix::actor< LeftExprT >, attribute_actor< T, FallbackPolicyT, TagT, phoenix::actor > >::type\ + operator<< (phoenix::actor< LeftExprT > left_ref left, attribute_actor< T, FallbackPolicyT, TagT, phoenix::actor > right_ref right)\ + {\ + return aux::make_output_actor< phoenix::actor< LeftExprT >, attribute_actor< T, FallbackPolicyT, TagT, phoenix::actor > >::make(left, right);\ + } + +#include <boost/log/detail/generate_overloads.hpp> + +#undef BOOST_LOG_AUX_OVERLOAD + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ATTR_OUTPUT_IMPL_HPP_INCLUDED_ diff --git a/boost/log/detail/attr_output_terminal.hpp b/boost/log/detail/attr_output_terminal.hpp new file mode 100644 index 0000000000..574993aace --- /dev/null +++ b/boost/log/detail/attr_output_terminal.hpp @@ -0,0 +1,162 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 attribute_output_terminal.hpp + * \author Andrey Semashev + * \date 06.11.2012 + * + * The header contains implementation of a generic output manipulator in template expressions. + */ + +#ifndef BOOST_LOG_DETAIL_ATTR_OUTPUT_TERMINAL_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ATTR_OUTPUT_TERMINAL_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/phoenix/core/actor.hpp> +#include <boost/phoenix/core/meta_grammar.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/fusion/sequence/intrinsic/at.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/value_visitation.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +//! Attribute stream output expression +template< typename LeftT, typename T, typename FallbackPolicyT, typename ImplT > +class attribute_output_terminal +{ +private: + //! Self type + typedef attribute_output_terminal< LeftT, T, FallbackPolicyT, ImplT > this_type; + //! Attribute value visitor invoker + typedef value_visitor_invoker< T, FallbackPolicyT > visitor_invoker_type; + //! Manipulator implementation + typedef ImplT impl_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Result type definition + template< typename > + struct result; + + template< typename ThisT, typename ContextT > + struct result< ThisT(ContextT) > + { + typedef typename remove_cv< typename remove_reference< ContextT >::type >::type context_type; + typedef typename phoenix::evaluator::impl< + typename LeftT::proto_base_expr&, + context_type, + phoenix::unused + >::result_type type; + }; + +private: + //! Left argument actor + LeftT m_left; + //! Attribute name + const attribute_name m_name; + //! Attribute value visitor invoker + visitor_invoker_type m_visitor_invoker; + //! Manipulator implementation + impl_type m_impl; + +public: + //! Initializing constructor + attribute_output_terminal(LeftT const& left, attribute_name const& name) : m_left(left), m_name(name) + { + } + + //! Initializing constructor + attribute_output_terminal(LeftT const& left, attribute_name const& name, impl_type const& impl) : m_left(left), m_name(name), m_impl(impl) + { + } + + //! Initializing constructor + template< typename U > + attribute_output_terminal(LeftT const& left, attribute_name const& name, impl_type const& impl, U const& arg) : + m_left(left), m_name(name), m_visitor_invoker(arg), m_impl(impl) + { + } + + //! Copy constructor + attribute_output_terminal(attribute_output_terminal const& that) : + m_left(that.m_left), m_name(that.m_name), m_visitor_invoker(that.m_visitor_invoker), m_impl(that.m_impl) + { + } + + //! Invokation operator + template< typename ContextT > + typename result< this_type(ContextT const&) >::type operator() (ContextT const& ctx) + { + typedef typename result< this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< impl_type&, result_type >(m_impl, strm)); + return strm; + } + + //! Invokation operator + template< typename ContextT > + typename result< const this_type(ContextT const&) >::type operator() (ContextT const& ctx) const + { + typedef typename result< const this_type(ContextT const&) >::type result_type; + result_type strm = phoenix::eval(m_left, ctx); + m_visitor_invoker(m_name, fusion::at_c< 0 >(phoenix::env(ctx).args()), binder1st< impl_type const&, result_type >(m_impl, strm)); + return strm; + } + + BOOST_DELETED_FUNCTION(attribute_output_terminal()) +}; + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename LeftT, typename T, typename FallbackPolicyT, typename ImplT > +struct is_nullary< custom_terminal< boost::log::expressions::aux::attribute_output_terminal< LeftT, T, FallbackPolicyT, ImplT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ATTR_OUTPUT_TERMINAL_HPP_INCLUDED_ diff --git a/boost/log/detail/attribute_get_value_impl.hpp b/boost/log/detail/attribute_get_value_impl.hpp new file mode 100644 index 0000000000..2058d65242 --- /dev/null +++ b/boost/log/detail/attribute_get_value_impl.hpp @@ -0,0 +1,43 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 attribute_get_value_impl.hpp + * \author Andrey Semashev + * \date 04.08.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_ATTRIBUTE_GET_VALUE_IMPL_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ATTRIBUTE_GET_VALUE_IMPL_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute.hpp> +#include <boost/log/attributes/attribute_value.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +inline attribute_value attribute::get_value() const +{ + return m_pImpl->get_value(); +} + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ATTRIBUTE_GET_VALUE_IMPL_HPP_INCLUDED_ diff --git a/boost/log/detail/attribute_predicate.hpp b/boost/log/detail/attribute_predicate.hpp new file mode 100644 index 0000000000..a0978632a2 --- /dev/null +++ b/boost/log/detail/attribute_predicate.hpp @@ -0,0 +1,116 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 attribute_predicate.hpp + * \author Andrey Semashev + * \date 02.09.2012 + * + * The header contains implementation of a generic predicate in template expressions. + */ + +#ifndef BOOST_LOG_DETAIL_ATTRIBUTE_PREDICATE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ATTRIBUTE_PREDICATE_HPP_INCLUDED_ + +#include <boost/phoenix/core/actor.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/attributes/value_visitation.hpp> +#include <boost/log/attributes/fallback_policy.hpp> +#include <boost/log/utility/functional/bind.hpp> +#include <boost/log/utility/functional/save_result.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +/*! + * The predicate checks if the attribute value satisfies a predicate. + */ +template< typename T, typename ArgT, typename PredicateT, typename FallbackPolicyT = fallback_to_none > +class attribute_predicate +{ +public: + //! Function result_type + typedef bool result_type; + //! Expected attribute value type + typedef T value_type; + //! Predicate type + typedef PredicateT predicate_type; + //! Argument type for the predicate + typedef ArgT argument_type; + //! Fallback policy + typedef FallbackPolicyT fallback_policy; + +private: + //! Argument for the predicate + const argument_type m_arg; + //! Attribute value name + const attribute_name m_name; + //! Visitor invoker + value_visitor_invoker< value_type, fallback_policy > m_visitor_invoker; + +public: + /*! + * Initializing constructor + * + * \param name Attribute name + * \param pred_arg The predicate argument + */ + attribute_predicate(attribute_name const& name, argument_type const& pred_arg) : m_arg(pred_arg), m_name(name) + { + } + + /*! + * Initializing constructor + * + * \param name Attribute name + * \param pred_arg The predicate argument + * \param arg Additional parameter for the fallback policy + */ + template< typename U > + attribute_predicate(attribute_name const& name, argument_type const& pred_arg, U const& arg) : m_arg(pred_arg), m_name(name), m_visitor_invoker(arg) + { + } + + /*! + * Checking operator + * + * \param arg A set of attribute values or a log record + * \return \c true if the log record contains the sought attribute value, \c false otherwise + */ + template< typename ArgumentT > + result_type operator() (ArgumentT const& arg) const + { + typedef binder2nd< predicate_type, argument_type const& > visitor_type; + + bool res = false; + m_visitor_invoker(m_name, arg, boost::log::save_result(visitor_type(predicate_type(), m_arg), res)); + return res; + } +}; + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ATTRIBUTE_PREDICATE_HPP_INCLUDED_ diff --git a/boost/log/detail/cleanup_scope_guard.hpp b/boost/log/detail/cleanup_scope_guard.hpp new file mode 100644 index 0000000000..dd2c0e170a --- /dev/null +++ b/boost/log/detail/cleanup_scope_guard.hpp @@ -0,0 +1,55 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 cleanup_scope_guard.hpp + * \author Andrey Semashev + * \date 11.03.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_CLEANUP_SCOPE_GUARD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_CLEANUP_SCOPE_GUARD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Cleanup scope guard +template< typename T > +struct cleanup_guard +{ + explicit cleanup_guard(T& obj) : m_Obj(obj) {} + ~cleanup_guard() { m_Obj.clear(); } + + // Copying prohibited + BOOST_DELETED_FUNCTION(cleanup_guard(cleanup_guard const&)) + BOOST_DELETED_FUNCTION(cleanup_guard& operator= (cleanup_guard const&)) + +private: + T& m_Obj; +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_CLEANUP_SCOPE_GUARD_HPP_INCLUDED_ diff --git a/boost/log/detail/code_conversion.hpp b/boost/log/detail/code_conversion.hpp new file mode 100644 index 0000000000..d49988bc21 --- /dev/null +++ b/boost/log/detail/code_conversion.hpp @@ -0,0 +1,119 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 code_conversion.hpp + * \author Andrey Semashev + * \date 08.11.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_ + +#include <locale> +#include <string> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const wchar_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::wstring& str2, std::locale const& loc = std::locale()); +#if !defined(BOOST_NO_CXX11_CHAR16_T) +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char16_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u16string& str2, std::locale const& loc = std::locale()); +#endif +#if !defined(BOOST_NO_CXX11_CHAR32_T) +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char32_t* str1, std::size_t len, std::string& str2, std::locale const& loc = std::locale()); +//! The function converts one string to the character type of another +BOOST_LOG_API void code_convert(const char* str1, std::size_t len, std::u32string& str2, std::locale const& loc = std::locale()); +#endif + +//! The function converts one string to the character type of another +template< typename CharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetTraitsT, typename TargetAllocatorT > +inline void code_convert(std::basic_string< CharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< CharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale()) +{ + str2.append(str1.c_str(), str1.size()); +} +//! The function converts one string to the character type of another +template< typename CharT, typename TargetTraitsT, typename TargetAllocatorT > +inline void code_convert(const CharT* str1, std::size_t len, std::basic_string< CharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& = std::locale()) +{ + str2.append(str1, len); +} + +//! The function converts one string to the character type of another +template< typename SourceCharT, typename SourceTraitsT, typename SourceAllocatorT, typename TargetCharT, typename TargetTraitsT, typename TargetAllocatorT > +inline void code_convert(std::basic_string< SourceCharT, SourceTraitsT, SourceAllocatorT > const& str1, std::basic_string< TargetCharT, TargetTraitsT, TargetAllocatorT >& str2, std::locale const& loc = std::locale()) +{ + aux::code_convert(str1.c_str(), str1.size(), str2, loc); +} + +//! The function converts the passed string to the narrow-character encoding +inline std::string const& to_narrow(std::string const& str) +{ + return str; +} + +//! The function converts the passed string to the narrow-character encoding +inline std::string const& to_narrow(std::string const& str, std::locale const&) +{ + return str; +} + +//! The function converts the passed string to the narrow-character encoding +inline std::string to_narrow(std::wstring const& str, std::locale const& loc = std::locale()) +{ + std::string res; + aux::code_convert(str, res, loc); + return res; +} + +//! The function converts the passed string to the wide-character encoding +inline std::wstring const& to_wide(std::wstring const& str) +{ + return str; +} + +//! The function converts the passed string to the wide-character encoding +inline std::wstring const& to_wide(std::wstring const& str, std::locale const&) +{ + return str; +} + +//! The function converts the passed string to the wide-character encoding +inline std::wstring to_wide(std::string const& str, std::locale const& loc = std::locale()) +{ + std::wstring res; + aux::code_convert(str, res, loc); + return res; +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_CODE_CONVERSION_HPP_INCLUDED_ diff --git a/boost/log/detail/config.hpp b/boost/log/detail/config.hpp new file mode 100644 index 0000000000..4d1e66b73c --- /dev/null +++ b/boost/log/detail/config.hpp @@ -0,0 +1,351 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 config.hpp + * \author Andrey Semashev + * \date 08.03.2007 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_ + +// This check must be before any system headers are included, or __MSVCRT_VERSION__ may get defined to 0x0600 +#if defined(__MINGW32__) && !defined(__MSVCRT_VERSION__) +// Target MinGW headers to at least MSVC 7.0 runtime by default. This will enable some useful functions. +#define __MSVCRT_VERSION__ 0x0700 +#endif + +#include <limits.h> // To bring in libc macros +#include <boost/config.hpp> + +#if defined(BOOST_NO_RTTI) +# error Boost.Log: RTTI is required by the library +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1600 +# define BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH +#endif + +#if defined(BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH) +#include <boost/preprocessor/stringize.hpp> +#endif + +#if !defined(BOOST_WINDOWS) +# ifndef BOOST_LOG_WITHOUT_DEBUG_OUTPUT +# define BOOST_LOG_WITHOUT_DEBUG_OUTPUT +# endif +# ifndef BOOST_LOG_WITHOUT_EVENT_LOG +# define BOOST_LOG_WITHOUT_EVENT_LOG +# endif +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_MSVC) + // For some reason MSVC 9.0 fails to link the library if static integral constants are defined in cpp +# define BOOST_LOG_BROKEN_STATIC_CONSTANTS_LINKAGE +# if _MSC_VER <= 1310 + // MSVC 7.1 sometimes fails to match out-of-class template function definitions with + // their declarations if the return type or arguments of the functions involve typename keyword + // and depend on the template parameters. +# define BOOST_LOG_BROKEN_TEMPLATE_DEFINITION_MATCHING +# endif +# if _MSC_VER <= 1400 + // Older MSVC versions reject friend declarations for class template specializations +# define BOOST_LOG_BROKEN_FRIEND_TEMPLATE_SPECIALIZATIONS +# endif +# if _MSC_VER <= 1600 + // MSVC up to 10.0 attempts to invoke copy constructor when initializing a const reference from rvalue returned from a function. + // This fails when the returned value cannot be copied (only moved): + // + // class base {}; + // class derived : public base { BOOST_MOVABLE_BUT_NOT_COPYABLE(derived) }; + // derived foo(); + // base const& var = foo(); // attempts to call copy constructor of derived +# define BOOST_LOG_BROKEN_REFERENCE_FROM_RVALUE_INIT +# endif +# if !defined(_STLPORT_VERSION) + // MSVC 9.0 mandates packaging of STL classes, which apparently affects alignment and + // makes alignment_of< T >::value no longer be a power of 2 for types that derive from STL classes. + // This breaks type_with_alignment and everything that relies on it. + // This doesn't happen with non-native STLs, such as STLPort. Strangely, this doesn't show with + // STL classes themselves or most of the user-defined derived classes. + // Not sure if that happens with other MSVC versions. + // See: http://svn.boost.org/trac/boost/ticket/1946 +# define BOOST_LOG_BROKEN_STL_ALIGNMENT +# endif +#endif + +#if defined(BOOST_INTEL) || defined(__SUNPRO_CC) + // Intel compiler and Sun Studio 12.3 have problems with friend declarations for nested class templates +# define BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS +#endif + +#if defined(BOOST_MSVC) && BOOST_MSVC <= 1600 + // MSVC cannot interpret constant expressions in certain contexts, such as non-type template parameters +# define BOOST_LOG_BROKEN_CONSTANT_EXPRESSIONS +#endif + +#if defined(__CYGWIN__) + // Boost.ASIO is broken on Cygwin +# define BOOST_LOG_NO_ASIO +#endif + +#if !defined(BOOST_LOG_USE_NATIVE_SYSLOG) && defined(BOOST_LOG_NO_ASIO) +# ifndef BOOST_LOG_WITHOUT_SYSLOG +# define BOOST_LOG_WITHOUT_SYSLOG +# endif +#endif + +#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 2) + // GCC 4.1 and 4.2 have buggy anonymous namespaces support, which interferes with symbol linkage +# define BOOST_LOG_ANONYMOUS_NAMESPACE namespace anonymous {} using namespace anonymous; namespace anonymous +#else +# define BOOST_LOG_ANONYMOUS_NAMESPACE namespace +#endif + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || (defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 6)) +// GCC up to 4.6 (inclusively) did not support expanding template argument packs into non-variadic template arguments +#define BOOST_LOG_NO_CXX11_ARG_PACKS_TO_NON_VARIADIC_ARGS_EXPANSION +#endif + +#if defined(_MSC_VER) +# define BOOST_LOG_NO_VTABLE __declspec(novtable) +#elif defined(__GNUC__) +# define BOOST_LOG_NO_VTABLE +#else +# define BOOST_LOG_NO_VTABLE +#endif + +// An MS-like compilers' extension that allows to optimize away the needless code +#if defined(_MSC_VER) +# define BOOST_LOG_ASSUME(expr) __assume(expr) +#else +# define BOOST_LOG_ASSUME(expr) +#endif + +// The statement marking unreachable branches of code to avoid warnings +#if defined(BOOST_CLANG) +# if __has_builtin(__builtin_unreachable) +# define BOOST_LOG_UNREACHABLE() __builtin_unreachable() +# endif +#elif defined(__GNUC__) +# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +# define BOOST_LOG_UNREACHABLE() __builtin_unreachable() +# endif +#elif defined(_MSC_VER) +# define BOOST_LOG_UNREACHABLE() __assume(0) +#endif +#if !defined(BOOST_LOG_UNREACHABLE) +# define BOOST_LOG_UNREACHABLE() +# define BOOST_LOG_UNREACHABLE_RETURN(r) return r +#else +# define BOOST_LOG_UNREACHABLE_RETURN(r) BOOST_LOG_UNREACHABLE() +#endif + +// Some compilers support a special attribute that shows that a function won't return +#if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590) + // GCC and Sun Studio 12 support attribute syntax +# define BOOST_LOG_NORETURN __attribute__((noreturn)) +#elif defined (_MSC_VER) + // Microsoft-compatible compilers go here +# define BOOST_LOG_NORETURN __declspec(noreturn) +#else + // The rest compilers might emit bogus warnings about missing return statements + // in functions with non-void return types when throw_exception is used. +# define BOOST_LOG_NORETURN +#endif + +#if !defined(BOOST_LOG_BUILDING_THE_LIB) + +// Detect if we're dealing with dll +# if defined(BOOST_LOG_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) +# define BOOST_LOG_DLL +# endif + +# if defined(BOOST_LOG_DLL) +# if defined(BOOST_SYMBOL_IMPORT) +# define BOOST_LOG_API BOOST_SYMBOL_IMPORT +# elif defined(BOOST_HAS_DECLSPEC) +# define BOOST_LOG_API __declspec(dllimport) +# endif +# endif +# ifndef BOOST_LOG_API +# define BOOST_LOG_API +# endif +// +// Automatically link to the correct build variant where possible. +// +# if !defined(BOOST_ALL_NO_LIB) +# if !defined(BOOST_LOG_NO_LIB) +# define BOOST_LIB_NAME boost_log +# if defined(BOOST_LOG_DLL) +# define BOOST_DYN_LINK +# endif +# include <boost/config/auto_link.hpp> +# endif + // In static-library builds compilers ignore auto-link comments from Boost.Log binary to + // other Boost libraries. We explicitly add comments here for other libraries. + // In dynamic-library builds this is not needed. +# if !defined(BOOST_LOG_DLL) +# include <boost/system/config.hpp> +# include <boost/filesystem/config.hpp> +# if !defined(BOOST_DATE_TIME_NO_LIB) && !defined(BOOST_DATE_TIME_SOURCE) +# define BOOST_LIB_NAME boost_date_time +# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_DATE_TIME_DYN_LINK) +# define BOOST_DYN_LINK +# endif +# include <boost/config/auto_link.hpp> +# endif + // Boost.Thread's config is included below, if needed +# endif +# endif // auto-linking disabled + +#else // !defined(BOOST_LOG_BUILDING_THE_LIB) + +# if defined(BOOST_LOG_DLL) +# if defined(BOOST_SYMBOL_EXPORT) +# define BOOST_LOG_API BOOST_SYMBOL_EXPORT +# elif defined(BOOST_HAS_DECLSPEC) +# define BOOST_LOG_API __declspec(dllexport) +# endif +# endif +# ifndef BOOST_LOG_API +# define BOOST_LOG_API BOOST_SYMBOL_VISIBLE +# endif + +#endif // !defined(BOOST_LOG_BUILDING_THE_LIB) + +// By default we provide support for both char and wchar_t +#if !defined(BOOST_LOG_WITHOUT_CHAR) +# define BOOST_LOG_USE_CHAR +#endif +#if !defined(BOOST_LOG_WITHOUT_WCHAR_T) +# define BOOST_LOG_USE_WCHAR_T +#endif + +#if !defined(BOOST_LOG_DOXYGEN_PASS) + // Check if multithreading is supported +# if !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_HAS_THREADS) +# define BOOST_LOG_NO_THREADS +# endif // !defined(BOOST_LOG_NO_THREADS) && !defined(BOOST_HAS_THREADS) +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +#if !defined(BOOST_LOG_NO_THREADS) + // We need this header to (i) enable auto-linking with Boost.Thread and + // (ii) to bring in configuration macros of Boost.Thread. +# include <boost/thread/detail/config.hpp> +#endif // !defined(BOOST_LOG_NO_THREADS) + +#if !defined(BOOST_LOG_NO_THREADS) +# define BOOST_LOG_EXPR_IF_MT(expr) expr +#else +# undef BOOST_LOG_USE_COMPILER_TLS +# define BOOST_LOG_EXPR_IF_MT(expr) +#endif // !defined(BOOST_LOG_NO_THREADS) + +#if defined(BOOST_LOG_USE_COMPILER_TLS) +# if defined(__GNUC__) || defined(__SUNPRO_CC) +# define BOOST_LOG_TLS __thread +# elif defined(BOOST_MSVC) +# define BOOST_LOG_TLS __declspec(thread) +# else +# undef BOOST_LOG_USE_COMPILER_TLS +# endif +#endif // defined(BOOST_LOG_USE_COMPILER_TLS) + +#ifndef BOOST_LOG_CPU_CACHE_LINE_SIZE +//! The macro defines the CPU cache line size for the target architecture. This is mostly used for optimization. +#define BOOST_LOG_CPU_CACHE_LINE_SIZE 64 +#endif + +namespace boost { + +// Setup namespace name +#if !defined(BOOST_LOG_DOXYGEN_PASS) +# if defined(BOOST_LOG_DLL) +# if defined(BOOST_LOG_NO_THREADS) +# define BOOST_LOG_VERSION_NAMESPACE v2_st +# else +# if defined(BOOST_THREAD_PLATFORM_PTHREAD) +# define BOOST_LOG_VERSION_NAMESPACE v2_mt_posix +# elif defined(BOOST_THREAD_PLATFORM_WIN32) +# if defined(BOOST_LOG_USE_WINNT6_API) +# define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt6 +# else +# define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt5 +# endif // defined(BOOST_LOG_USE_WINNT6_API) +# else +# define BOOST_LOG_VERSION_NAMESPACE v2_mt +# endif +# endif // defined(BOOST_LOG_NO_THREADS) +# else +# if defined(BOOST_LOG_NO_THREADS) +# define BOOST_LOG_VERSION_NAMESPACE v2s_st +# else +# if defined(BOOST_THREAD_PLATFORM_PTHREAD) +# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_posix +# elif defined(BOOST_THREAD_PLATFORM_WIN32) +# if defined(BOOST_LOG_USE_WINNT6_API) +# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt6 +# else +# define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt5 +# endif // defined(BOOST_LOG_USE_WINNT6_API) +# else +# define BOOST_LOG_VERSION_NAMESPACE v2s_mt +# endif +# endif // defined(BOOST_LOG_NO_THREADS) +# endif // defined(BOOST_LOG_DLL) + + +namespace log { + +# if !defined(BOOST_NO_CXX11_INLINE_NAMESPACES) + +inline namespace BOOST_LOG_VERSION_NAMESPACE {} +} + +# define BOOST_LOG_OPEN_NAMESPACE namespace log { inline namespace BOOST_LOG_VERSION_NAMESPACE { +# define BOOST_LOG_CLOSE_NAMESPACE }} + +# else + +namespace BOOST_LOG_VERSION_NAMESPACE {} + +using namespace BOOST_LOG_VERSION_NAMESPACE +# if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && !defined(__clang__) +__attribute__((__strong__)) +# endif +; + +} + +# define BOOST_LOG_OPEN_NAMESPACE namespace log { namespace BOOST_LOG_VERSION_NAMESPACE { +# define BOOST_LOG_CLOSE_NAMESPACE }} +# endif + +#else // !defined(BOOST_LOG_DOXYGEN_PASS) + +namespace log {} +# define BOOST_LOG_OPEN_NAMESPACE namespace log { +# define BOOST_LOG_CLOSE_NAMESPACE } + +#endif // !defined(BOOST_LOG_DOXYGEN_PASS) + +#if defined(BOOST_LOG_HAS_PRAGMA_DETECT_MISMATCH) +#pragma detect_mismatch("boost_log_abi", BOOST_PP_STRINGIZE(BOOST_LOG_VERSION_NAMESPACE)) +#endif + +} // namespace boost + +#endif // BOOST_LOG_DETAIL_CONFIG_HPP_INCLUDED_ diff --git a/boost/log/detail/copy_cv.hpp b/boost/log/detail/copy_cv.hpp new file mode 100644 index 0000000000..a6a4ebae04 --- /dev/null +++ b/boost/log/detail/copy_cv.hpp @@ -0,0 +1,64 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 copy_cv.hpp + * \author Andrey Semashev + * \date 16.03.2014 + * + * The header defines \c copy_cv type trait which copies const/volatile qualifiers from one type to another + */ + +#ifndef BOOST_LOG_DETAIL_COPY_CV_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_COPY_CV_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The type trait copies top level const/volatile qualifiers from \c FromT to \c ToT +template< typename FromT, typename ToT > +struct copy_cv +{ + typedef ToT type; +}; + +template< typename FromT, typename ToT > +struct copy_cv< const FromT, ToT > +{ + typedef const ToT type; +}; + +template< typename FromT, typename ToT > +struct copy_cv< volatile FromT, ToT > +{ + typedef volatile ToT type; +}; + +template< typename FromT, typename ToT > +struct copy_cv< const volatile FromT, ToT > +{ + typedef const volatile ToT type; +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_COPY_CV_HPP_INCLUDED_ diff --git a/boost/log/detail/custom_terminal_spec.hpp b/boost/log/detail/custom_terminal_spec.hpp new file mode 100644 index 0000000000..fb43357b00 --- /dev/null +++ b/boost/log/detail/custom_terminal_spec.hpp @@ -0,0 +1,70 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 custom_terminal_spec.hpp + * \author Andrey Semashev + * \date 29.01.2012 + * + * The header contains Boost.Phoenix custom terminal specialization for Boost.Log terminals. + */ + +#ifndef BOOST_LOG_DETAIL_CUSTOM_TERMINAL_SPEC_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_CUSTOM_TERMINAL_SPEC_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/phoenix/core/terminal_fwd.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/terminal.hpp> // needed for terminal-related part of the grammar +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +namespace phoenix { + +template< typename T > +struct is_custom_terminal< T, typename T::_is_boost_log_terminal > : + public mpl::true_ +{ +}; + +template< typename T > +struct custom_terminal< T, typename T::_is_boost_log_terminal > +{ + typedef custom_terminal< T, typename T::_is_boost_log_terminal > this_type; + + template< typename > + struct result; + + template< typename ThisT, typename TermT, typename ContextT > + struct result< ThisT(TermT, ContextT) > + { + typedef typename remove_cv< typename remove_reference< TermT >::type >::type term; + typedef typename boost::result_of< const term(ContextT) >::type type; + }; + + template< typename ContextT > + typename result< const this_type(T const&, ContextT&) >::type operator() (T const& term, ContextT& ctx) const + { + return term(ctx); + } +}; + +} // namespace phoenix + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_CUSTOM_TERMINAL_SPEC_HPP_INCLUDED_ diff --git a/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp b/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp new file mode 100644 index 0000000000..a80930b2ae --- /dev/null +++ b/boost/log/detail/date_time_fmt_gen_traits_fwd.hpp @@ -0,0 +1,44 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 date_time_fmt_gen_traits_fwd.hpp + * \author Andrey Semashev + * \date 07.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_DATE_TIME_FMT_GEN_TRAITS_FWD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DATE_TIME_FMT_GEN_TRAITS_FWD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +template< typename T, typename CharT, typename VoidT = void > +struct date_time_formatter_generator_traits; + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_DETAIL_DATE_TIME_FMT_GEN_TRAITS_FWD_HPP_INCLUDED_ diff --git a/boost/log/detail/date_time_format_parser.hpp b/boost/log/detail/date_time_format_parser.hpp new file mode 100644 index 0000000000..7b82d5556a --- /dev/null +++ b/boost/log/detail/date_time_format_parser.hpp @@ -0,0 +1,486 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 date_time_format_parser.hpp + * \author Andrey Semashev + * \date 16.09.2012 + * + * The header contains a parser for date and time format strings. + */ + +#ifndef BOOST_LOG_DETAIL_DATE_TIME_FORMAT_PARSER_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DATE_TIME_FORMAT_PARSER_HPP_INCLUDED_ + +#include <string> +#include <boost/range/as_literal.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +/*! + * This is the interface the parser will use to notify the caller about various components of date in the format string. + */ +template< typename CharT > +struct date_format_parser_callback +{ + //! Character type used by the parser + typedef CharT char_type; + + //! Destructor + virtual ~date_format_parser_callback() {} + + /*! + * \brief The function is called when the parser discovers a string literal in the format string + * + * \param lit The string of characters not interpreted as a placeholder + */ + virtual void on_literal(iterator_range< const char_type* > const& lit) = 0; + + /*! + * \brief The method is called when an unknown placeholder is found in the format string + * + * \param ph The placeholder with the leading percent sign + */ + virtual void on_placeholder(iterator_range< const char_type* > const& ph) + { + // By default interpret all unrecognized placeholders as literals + on_literal(ph); + } + + /*! + * \brief The function is called when the short year placeholder is found in the format string + */ + virtual void on_short_year() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('y'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the full year placeholder is found in the format string + */ + virtual void on_full_year() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('Y'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the numeric month placeholder is found in the format string + */ + virtual void on_numeric_month() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('m'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the short alphabetic month placeholder is found in the format string + */ + virtual void on_short_month() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('b'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the full alphabetic month placeholder is found in the format string + */ + virtual void on_full_month() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('B'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the numeric day of month placeholder is found in the format string + * + * \param leading_zero If \c true, the day should be formatted with leading zero, otherwise with leading space + */ + virtual void on_month_day(bool leading_zero) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (leading_zero ? static_cast< char_type >('d') : static_cast< char_type >('e')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the numeric day of week placeholder is found in the format string + */ + virtual void on_numeric_week_day() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('w'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the short alphabetic day of week placeholder is found in the format string + */ + virtual void on_short_week_day() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('a'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the full alphabetic day of week placeholder is found in the format string + */ + virtual void on_full_week_day() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('A'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the ISO-formatted date is found in the format string + */ + virtual void on_iso_date() + { + on_full_year(); + on_numeric_month(); + on_month_day(true); + } + + /*! + * \brief The function is called when the extended ISO-formatted date is found in the format string + */ + virtual void on_extended_iso_date() + { + const char_type delimiter[2] = { static_cast< char_type >('-'), static_cast< char_type >('\0') }; + on_full_year(); + on_literal(boost::as_literal(delimiter)); + on_numeric_month(); + on_literal(boost::as_literal(delimiter)); + on_month_day(true); + } +}; + +/*! + * This is the interface the parser will use to notify the caller about various components of date in the format string. + */ +template< typename CharT > +struct time_format_parser_callback +{ + //! Character type used by the parser + typedef CharT char_type; + + //! Destructor + virtual ~time_format_parser_callback() {} + + /*! + * \brief The function is called when the parser discovers a string literal in the format string + * + * \param lit The string of characters not interpreted as a placeholder + */ + virtual void on_literal(iterator_range< const char_type* > const& lit) = 0; + + /*! + * \brief The method is called when an unknown placeholder is found in the format string + * + * \param ph The placeholder with the leading percent sign + */ + virtual void on_placeholder(iterator_range< const char_type* > const& ph) + { + // By default interpret all unrecognized placeholders as literals + on_literal(ph); + } + + /*! + * \brief The function is called when the hours placeholder is found in the format string + * + * The placeholder is used for 24-hour clock and duration formatting. + * + * \param leading_zero If \c true, the one-digit number of hours should be formatted with leading zero, otherwise with leading space + */ + virtual void on_hours(bool leading_zero) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (leading_zero ? static_cast< char_type >('O') : static_cast< char_type >('k')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the hours placeholder is found in the format string + * + * The placeholder is used for 12-hour clock formatting. It should not be used for duration formatting. + * + * \param leading_zero If \c true, the one-digit number of hours should be formatted with leading zero, otherwise with leading space + */ + virtual void on_hours_12(bool leading_zero) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (leading_zero ? static_cast< char_type >('I') : static_cast< char_type >('l')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the minutes placeholder is found in the format string + */ + virtual void on_minutes() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('M'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the seconds placeholder is found in the format string + */ + virtual void on_seconds() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('S'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the fractional seconds placeholder is found in the format string + */ + virtual void on_fractional_seconds() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('f'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the day period (AM/PM) placeholder is found in the format string + * + * The placeholder is used for 12-hour clock formatting. It should not be used for duration formatting. + * + * \param upper_case If \c true, the day period will be upper case, and lower case otherwise + */ + virtual void on_am_pm(bool upper_case) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (upper_case ? static_cast< char_type >('p') : static_cast< char_type >('P')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the time duration sign placeholder is found in the format string + * + * The placeholder is used for duration formatting. It should not be used for time point formatting. + * + * \param display_positive If \c true, the positive sign will be explicitly displayed, otherwise only negative sign will be displayed + */ + virtual void on_duration_sign(bool display_positive) + { + const char_type placeholder[3] = { static_cast< char_type >('%'), (display_positive ? static_cast< char_type >('+') : static_cast< char_type >('-')), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the ISO time zone placeholder is found in the format string + */ + virtual void on_iso_time_zone() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('q'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the extended ISO time zone placeholder is found in the format string + */ + virtual void on_extended_iso_time_zone() + { + const char_type placeholder[3] = { static_cast< char_type >('%'), static_cast< char_type >('Q'), static_cast< char_type >('\0') }; + on_placeholder(boost::as_literal(placeholder)); + } + + /*! + * \brief The function is called when the ISO-formatted time is found in the format string + */ + virtual void on_iso_time() + { + on_hours(true); + on_minutes(); + on_seconds(); + } + + /*! + * \brief The function is called when the extended ISO-formatted time is found in the format string + */ + virtual void on_extended_iso_time() + { + const char_type delimiter[2] = { static_cast< char_type >(':'), static_cast< char_type >('\0') }; + on_hours(true); + on_literal(boost::as_literal(delimiter)); + on_minutes(); + on_literal(boost::as_literal(delimiter)); + on_seconds(); + } + + /*! + * \brief The function is called when the extended ISO-formatted time with fractional seconds is found in the format string + */ + virtual void on_default_time() + { + on_extended_iso_time(); + + const char_type delimiter[2] = { static_cast< char_type >('.'), static_cast< char_type >('\0') }; + on_literal(boost::as_literal(delimiter)); + on_fractional_seconds(); + } +}; + +/*! + * This is the interface the parser will use to notify the caller about various components of date in the format string. + */ +template< typename CharT > +struct date_time_format_parser_callback : + public date_format_parser_callback< CharT >, + public time_format_parser_callback< CharT > +{ + //! Character type used by the parser + typedef CharT char_type; + + //! Destructor + virtual ~date_time_format_parser_callback() {} + + /*! + * \brief The function is called when the parser discovers a string literal in the format string + * + * \param lit The string of characters not interpreted as a placeholder + */ + virtual void on_literal(iterator_range< const char_type* > const& lit) = 0; + + /*! + * \brief The method is called when an unknown placeholder is found in the format string + * + * \param ph The placeholder with the leading percent sign + */ + virtual void on_placeholder(iterator_range< const char_type* > const& ph) + { + // By default interpret all unrecognized placeholders as literals + on_literal(ph); + } +}; + +/*! + * \brief Parses the date format string and invokes the callback object + * + * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL + * \param begin Pointer to the first character of the sequence + * \param end Pointer to the after-the-last character of the sequence + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +BOOST_LOG_API void parse_date_format(const CharT* begin, const CharT* end, date_format_parser_callback< CharT >& callback); + +/*! + * \brief Parses the date format string and invokes the callback object + * + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +inline void parse_date_format(std::basic_string< CharT, TraitsT, AllocatorT > const& str, date_format_parser_callback< CharT >& callback) +{ + const CharT* p = str.c_str(); + return parse_date_format(p, p + str.size(), callback); +} + +/*! + * \brief Parses the date format string and invokes the callback object + * + * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string. + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +inline void parse_date_format(const CharT* str, date_format_parser_callback< CharT >& callback) +{ + return parse_date_format(str, str + std::char_traits< CharT >::length(str), callback); +} + +/*! + * \brief Parses the time format string and invokes the callback object + * + * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL + * \param begin Pointer to the first character of the sequence + * \param end Pointer to the after-the-last character of the sequence + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +BOOST_LOG_API void parse_time_format(const CharT* begin, const CharT* end, time_format_parser_callback< CharT >& callback); + +/*! + * \brief Parses the time format string and invokes the callback object + * + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +inline void parse_time_format(std::basic_string< CharT, TraitsT, AllocatorT > const& str, time_format_parser_callback< CharT >& callback) +{ + const CharT* p = str.c_str(); + return parse_time_format(p, p + str.size(), callback); +} + +/*! + * \brief Parses the time format string and invokes the callback object + * + * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string. + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +inline void parse_time_format(const CharT* str, time_format_parser_callback< CharT >& callback) +{ + return parse_time_format(str, str + std::char_traits< CharT >::length(str), callback); +} + +/*! + * \brief Parses the date and time format string and invokes the callback object + * + * \pre <tt>begin <= end</tt>, both pointers must not be \c NULL + * \param begin Pointer to the first character of the sequence + * \param end Pointer to the after-the-last character of the sequence + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +BOOST_LOG_API void parse_date_time_format(const CharT* begin, const CharT* end, date_time_format_parser_callback< CharT >& callback); + +/*! + * \brief Parses the date and time format string and invokes the callback object + * + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT, typename TraitsT, typename AllocatorT > +inline void parse_date_time_format(std::basic_string< CharT, TraitsT, AllocatorT > const& str, date_time_format_parser_callback< CharT >& callback) +{ + const CharT* p = str.c_str(); + return parse_date_time_format(p, p + str.size(), callback); +} + +/*! + * \brief Parses the date and time format string and invokes the callback object + * + * \pre <tt>str != NULL</tt>, <tt>str</tt> points to a zero-terminated string. + * \param str The format string to parse + * \param callback Reference to the callback object that will be invoked by the parser as it processes the input + */ +template< typename CharT > +inline void parse_date_time_format(const CharT* str, date_time_format_parser_callback< CharT >& callback) +{ + return parse_date_time_format(str, str + std::char_traits< CharT >::length(str), callback); +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_DATE_TIME_FORMAT_PARSER_HPP_INCLUDED_ diff --git a/boost/log/detail/decomposed_time.hpp b/boost/log/detail/decomposed_time.hpp new file mode 100644 index 0000000000..24f7546533 --- /dev/null +++ b/boost/log/detail/decomposed_time.hpp @@ -0,0 +1,440 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 decomposed_time.hpp + * \author Andrey Semashev + * \date 07.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_ + +#include <ctime> +#include <string> +#include <vector> +#include <locale> +#include <boost/cstdint.hpp> +#include <boost/move/core.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/date_time_format_parser.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 + +namespace aux { + +//! Date and time suitable for formatting +struct decomposed_time +{ + // Subseconds are microseconds + enum _ + { + subseconds_per_second = 1000000, + subseconds_digits10 = 6 + }; + + uint32_t year, month, day, hours, minutes, seconds, subseconds; + bool negative; + + decomposed_time() : year(0), month(1), day(1), hours(0), minutes(0), seconds(0), subseconds(0), negative(false) + { + } + + decomposed_time(uint32_t y, uint32_t mo, uint32_t d, uint32_t h, uint32_t mi, uint32_t s, uint32_t ss = 0, bool neg = false) : + year(y), month(mo), day(d), hours(h), minutes(mi), seconds(s), subseconds(ss), negative(neg) + { + } + + unsigned int week_day() const + { + unsigned int a = (14u - month) / 12u; + unsigned int y = year - a; + unsigned int m = month + 12u * a - 2u; + return (day + y + (y / 4u) - (y / 100u) + (y / 400u) + (31u * m) / 12u) % 7u; + } + + unsigned int year_day() const + { + bool is_leap_year = (!(year % 4u)) && ((year % 100u) || (!(year % 400u))); + static const unsigned int first_day_offset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + return first_day_offset[month - 1] + day + (month > 2 && is_leap_year); + } +}; + +inline std::tm to_tm(decomposed_time const& t) +{ + std::tm res = {}; + res.tm_year = static_cast< int >(t.year) - 1900; + res.tm_mon = t.month - 1; + res.tm_mday = t.day; + res.tm_hour = t.hours; + res.tm_min = t.minutes; + res.tm_sec = t.seconds; + res.tm_wday = t.week_day(); + res.tm_yday = t.year_day(); + res.tm_isdst = -1; + + return res; +} + +template< typename T > +struct decomposed_time_wrapper : + public boost::log::aux::decomposed_time +{ + typedef boost::log::aux::decomposed_time base_type; + typedef T value_type; + value_type m_time; + + BOOST_DEFAULTED_FUNCTION(decomposed_time_wrapper(), {}) + + explicit decomposed_time_wrapper(value_type const& time) : m_time(time) + { + } +}; + +template< typename CharT > +BOOST_LOG_API void put_integer(std::basic_string< CharT >& str, uint32_t value, unsigned int width, CharT fill_char); + +template< typename T, typename CharT > +class date_time_formatter +{ + BOOST_COPYABLE_AND_MOVABLE_ALT(date_time_formatter) + +protected: + // Note: This typedef is needed to work around MSVC 2012 crappy name lookup in the derived classes + typedef date_time_formatter date_time_formatter_; + +public: + typedef void result_type; + typedef T value_type; + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef basic_formatting_ostream< char_type > stream_type; + + struct context + { + date_time_formatter const& self; + stream_type& strm; + string_type& str; + value_type const& value; + unsigned int literal_index, literal_pos; + + context(date_time_formatter const& self_, stream_type& strm_, value_type const& value_) : + self(self_), + strm(strm_), + str(*strm_.rdbuf()->storage()), + value(value_), + literal_index(0), + literal_pos(0) + { + } + + BOOST_DELETED_FUNCTION(context(context const&)) + BOOST_DELETED_FUNCTION(context& operator=(context const&)) + }; + +private: + typedef void (*formatter_type)(context&); + typedef std::vector< formatter_type > formatters; + typedef std::vector< unsigned int > literal_lens; + +protected: + formatters m_formatters; + literal_lens m_literal_lens; + string_type m_literal_chars; + +public: + BOOST_DEFAULTED_FUNCTION(date_time_formatter(), {}) + date_time_formatter(date_time_formatter const& that) : + m_formatters(that.m_formatters), + m_literal_lens(that.m_literal_lens), + m_literal_chars(that.m_literal_chars) + { + } + date_time_formatter(BOOST_RV_REF(date_time_formatter) that) + { + this->swap(static_cast< date_time_formatter& >(that)); + } + + date_time_formatter& operator= (date_time_formatter that) + { + this->swap(that); + return *this; + } + + result_type operator() (stream_type& strm, value_type const& value) const + { + // Some formatters will put characters directly to the underlying string, so we have to flush stream buffers before formatting + strm.flush(); + context ctx(*this, strm, value); + for (typename formatters::const_iterator it = m_formatters.begin(), end = m_formatters.end(); strm.good() && it != end; ++it) + { + (*it)(ctx); + } + } + + void add_formatter(formatter_type fun) + { + m_formatters.push_back(fun); + } + + void add_literal(iterator_range< const char_type* > const& lit) + { + m_literal_chars.append(lit.begin(), lit.end()); + m_literal_lens.push_back(static_cast< unsigned int >(lit.size())); + m_formatters.push_back(&date_time_formatter_::format_literal); + } + + void swap(date_time_formatter& that) + { + m_formatters.swap(that.m_formatters); + m_literal_lens.swap(that.m_literal_lens); + m_literal_chars.swap(that.m_literal_chars); + } + +public: + template< char FormatCharV > + static void format_through_locale(context& ctx) + { + typedef std::time_put< char_type > facet_type; + typedef typename facet_type::iter_type iter_type; + std::tm t = to_tm(static_cast< decomposed_time const& >(ctx.value)); + std::use_facet< facet_type >(ctx.strm.getloc()).put(iter_type(ctx.strm.stream()), ctx.strm.stream(), ' ', &t, FormatCharV); + ctx.strm.flush(); + } + + static void format_full_year(context& ctx) + { + (put_integer)(ctx.str, ctx.value.year, 4, static_cast< char_type >('0')); + } + + static void format_short_year(context& ctx) + { + (put_integer)(ctx.str, ctx.value.year % 100u, 2, static_cast< char_type >('0')); + } + + static void format_numeric_month(context& ctx) + { + (put_integer)(ctx.str, ctx.value.month, 2, static_cast< char_type >('0')); + } + + template< char_type FillCharV > + static void format_month_day(context& ctx) + { + (put_integer)(ctx.str, ctx.value.day, 2, static_cast< char_type >(FillCharV)); + } + + static void format_week_day(context& ctx) + { + (put_integer)(ctx.str, static_cast< decomposed_time const& >(ctx.value).week_day(), 1, static_cast< char_type >('0')); + } + + template< char_type FillCharV > + static void format_hours(context& ctx) + { + (put_integer)(ctx.str, ctx.value.hours, 2, static_cast< char_type >(FillCharV)); + } + + template< char_type FillCharV > + static void format_hours_12(context& ctx) + { + (put_integer)(ctx.str, ctx.value.hours % 12u + 1u, 2, static_cast< char_type >(FillCharV)); + } + + static void format_minutes(context& ctx) + { + (put_integer)(ctx.str, ctx.value.minutes, 2, static_cast< char_type >('0')); + } + + static void format_seconds(context& ctx) + { + (put_integer)(ctx.str, ctx.value.seconds, 2, static_cast< char_type >('0')); + } + + static void format_fractional_seconds(context& ctx) + { + (put_integer)(ctx.str, ctx.value.subseconds, decomposed_time::subseconds_digits10, static_cast< char_type >('0')); + } + + template< bool UpperCaseV > + static void format_am_pm(context& ctx) + { + static const char_type am[] = { static_cast< char_type >(UpperCaseV ? 'A' : 'a'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) }; + static const char_type pm[] = { static_cast< char_type >(UpperCaseV ? 'P' : 'p'), static_cast< char_type >(UpperCaseV ? 'M' : 'm'), static_cast< char_type >(0) }; + + ctx.str.append(((static_cast< decomposed_time const& >(ctx.value).hours > 11) ? pm : am), 2u); + } + + template< bool DisplayPositiveV > + static void format_sign(context& ctx) + { + if (static_cast< decomposed_time const& >(ctx.value).negative) + ctx.str.push_back('-'); + else if (DisplayPositiveV) + ctx.str.push_back('+'); + } + +private: + static void format_literal(context& ctx) + { + unsigned int len = ctx.self.m_literal_lens[ctx.literal_index], pos = ctx.literal_pos; + ++ctx.literal_index; + ctx.literal_pos += len; + const char_type* lit = ctx.self.m_literal_chars.c_str(); + ctx.str.append(lit + pos, len); + } +}; + +template< typename FormatterT, typename CharT > +class decomposed_time_formatter_builder : + public date_time_format_parser_callback< CharT > +{ +public: + typedef date_time_format_parser_callback< CharT > base_type; + typedef typename base_type::char_type char_type; + typedef FormatterT formatter_type; + typedef typename formatter_type::value_type value_type; + typedef typename formatter_type::stream_type stream_type; + typedef typename stream_type::string_type string_type; + +protected: + formatter_type& m_formatter; + +public: + explicit decomposed_time_formatter_builder(formatter_type& fmt) : m_formatter(fmt) + { + } + + void on_literal(iterator_range< const char_type* > const& lit) + { + m_formatter.add_literal(lit); + } + + void on_short_year() + { + m_formatter.add_formatter(&formatter_type::format_short_year); + } + + void on_full_year() + { + m_formatter.add_formatter(&formatter_type::format_full_year); + } + + void on_numeric_month() + { + m_formatter.add_formatter(&formatter_type::format_numeric_month); + } + + void on_short_month() + { + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'b' >); + } + + void on_full_month() + { + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'B' >); + } + + void on_month_day(bool leading_zero) + { + if (leading_zero) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_month_day< '0' >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_month_day< ' ' >); + } + + void on_numeric_week_day() + { + m_formatter.add_formatter(&formatter_type::format_week_day); + } + + void on_short_week_day() + { + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'a' >); + } + + void on_full_week_day() + { + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_through_locale< 'A' >); + } + + void on_hours(bool leading_zero) + { + if (leading_zero) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours< '0' >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours< ' ' >); + } + + void on_hours_12(bool leading_zero) + { + if (leading_zero) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours_12< '0' >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_hours_12< ' ' >); + } + + void on_minutes() + { + m_formatter.add_formatter(&formatter_type::format_minutes); + } + + void on_seconds() + { + m_formatter.add_formatter(&formatter_type::format_seconds); + } + + void on_fractional_seconds() + { + m_formatter.add_formatter(&formatter_type::format_fractional_seconds); + } + + void on_am_pm(bool upper_case) + { + if (upper_case) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_am_pm< true >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_am_pm< false >); + } + + void on_duration_sign(bool display_positive) + { + if (display_positive) + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_sign< true >); + else + m_formatter.add_formatter(&formatter_type::BOOST_NESTED_TEMPLATE format_sign< false >); + } + + void on_iso_time_zone() + { + } + + void on_extended_iso_time_zone() + { + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_DECOMPOSED_TIME_HPP_INCLUDED_ diff --git a/boost/log/detail/deduce_char_type.hpp b/boost/log/detail/deduce_char_type.hpp new file mode 100644 index 0000000000..cb024609e9 --- /dev/null +++ b/boost/log/detail/deduce_char_type.hpp @@ -0,0 +1,108 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 deduce_char_type.hpp + * \author Andrey Semashev + * \date 17.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_DEDUCE_CHAR_TYPE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DEDUCE_CHAR_TYPE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T > +struct deduced_char_type; + +template< > +struct deduced_char_type< char > +{ + typedef char type; +}; + +template< > +struct deduced_char_type< const char > +{ + typedef char type; +}; + +template< > +struct deduced_char_type< wchar_t > +{ + typedef wchar_t type; +}; + +template< > +struct deduced_char_type< const wchar_t > +{ + typedef wchar_t type; +}; + +//! Auxiliary traits to detect character type from a string +template< typename RangeT > +struct deduce_char_type : + public deduced_char_type< typename RangeT::value_type > +{ +}; + +template< typename T > +struct deduce_char_type< T* > : + public deduced_char_type< T > +{ +}; + +template< typename T > +struct deduce_char_type< T* const > : + public deduced_char_type< T > +{ +}; + +template< typename T, unsigned int CountV > +struct deduce_char_type< T[CountV] > : + public deduced_char_type< T > +{ +}; + +template< typename T > +struct deduce_char_type< T& > : + public deduce_char_type< T > +{ +}; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename T > +struct deduce_char_type< T&& > : + public deduce_char_type< T > +{ +}; + +#endif + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_DEDUCE_CHAR_TYPE_HPP_INCLUDED_ diff --git a/boost/log/detail/default_attribute_names.hpp b/boost/log/detail/default_attribute_names.hpp new file mode 100644 index 0000000000..c1fddd36e3 --- /dev/null +++ b/boost/log/detail/default_attribute_names.hpp @@ -0,0 +1,53 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 default_attribute_names.hpp + * \author Andrey Semashev + * \date 15.01.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_DEFAULT_ATTRIBUTE_NAMES_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_DEFAULT_ATTRIBUTE_NAMES_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/attributes/attribute_name.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +namespace default_attribute_names { + +BOOST_LOG_API attribute_name severity(); +BOOST_LOG_API attribute_name channel(); +BOOST_LOG_API attribute_name message(); +BOOST_LOG_API attribute_name line_id(); +BOOST_LOG_API attribute_name timestamp(); +BOOST_LOG_API attribute_name process_id(); +BOOST_LOG_API attribute_name thread_id(); + +} // namespace default_attribute_names + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_DEFAULT_ATTRIBUTE_NAMES_HPP_INCLUDED_ diff --git a/boost/log/detail/embedded_string_type.hpp b/boost/log/detail/embedded_string_type.hpp new file mode 100644 index 0000000000..091dce205b --- /dev/null +++ b/boost/log/detail/embedded_string_type.hpp @@ -0,0 +1,125 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 embedded_string_type.hpp + * \author Andrey Semashev + * \date 16.08.2009 + * + * This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_ + +#include <string> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T, typename ArgT > +struct make_embedded_string_type_impl +{ + typedef ArgT type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< char, ArgT > +{ + typedef std::basic_string< char > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< const char, ArgT > +{ + typedef std::basic_string< char > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< wchar_t, ArgT > +{ + typedef std::basic_string< wchar_t > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< const wchar_t, ArgT > +{ + typedef std::basic_string< wchar_t > type; +}; + +#if !defined(BOOST_NO_CXX11_CHAR16_T) +template< typename ArgT > +struct make_embedded_string_type_impl< char16_t, ArgT > +{ + typedef std::basic_string< char16_t > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< const char16_t, ArgT > +{ + typedef std::basic_string< char16_t > type; +}; +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) +template< typename ArgT > +struct make_embedded_string_type_impl< char32_t, ArgT > +{ + typedef std::basic_string< char32_t > type; +}; + +template< typename ArgT > +struct make_embedded_string_type_impl< const char32_t, ArgT > +{ + typedef std::basic_string< char32_t > type; +}; +#endif + +//! An auxiliary type translator to store strings by value in function objects and attribute values +template< typename ArgT > +struct make_embedded_string_type : + public remove_cv< ArgT > +{ +}; + +template< typename ArgT > +struct make_embedded_string_type< ArgT* > : + public make_embedded_string_type_impl< ArgT, ArgT* > +{ +}; + +template< typename ArgT, unsigned int CountV > +struct make_embedded_string_type< ArgT[CountV] > : + public make_embedded_string_type_impl< ArgT, ArgT[CountV] > +{ +}; + +template< typename ArgT, unsigned int CountV > +struct make_embedded_string_type< ArgT(&)[CountV] > : + public make_embedded_string_type_impl< ArgT, ArgT(&)[CountV] > +{ +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_EMBEDDED_STRING_TYPE_HPP_INCLUDED_ diff --git a/boost/log/detail/enqueued_record.hpp b/boost/log/detail/enqueued_record.hpp new file mode 100644 index 0000000000..11aaf186f5 --- /dev/null +++ b/boost/log/detail/enqueued_record.hpp @@ -0,0 +1,103 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 enqueued_record.hpp + * \author Andrey Semashev + * \date 01.04.2014 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_ + +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/timestamp.hpp> +#include <boost/log/core/record_view.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace sinks { + +namespace aux { + +//! Log record with enqueueing timestamp +class enqueued_record +{ + BOOST_COPYABLE_AND_MOVABLE(enqueued_record) + +public: + //! Ordering predicate + template< typename OrderT > + struct order : + public OrderT + { + typedef typename OrderT::result_type result_type; + + order() {} + order(order const& that) : OrderT(static_cast< OrderT const& >(that)) {} + order(OrderT const& that) : OrderT(that) {} + + result_type operator() (enqueued_record const& left, enqueued_record const& right) const + { + // std::priority_queue requires ordering with semantics of std::greater, so we swap arguments + return OrderT::operator() (right.m_record, left.m_record); + } + }; + + boost::log::aux::timestamp m_timestamp; + record_view m_record; + + enqueued_record(enqueued_record const& that) : m_timestamp(that.m_timestamp), m_record(that.m_record) + { + } + enqueued_record(BOOST_RV_REF(enqueued_record) that) : + m_timestamp(that.m_timestamp), + m_record(boost::move(that.m_record)) + { + } + explicit enqueued_record(record_view const& rec) : + m_timestamp(boost::log::aux::get_timestamp()), + m_record(rec) + { + } + enqueued_record& operator= (BOOST_COPY_ASSIGN_REF(enqueued_record) that) + { + m_timestamp = that.m_timestamp; + m_record = that.m_record; + return *this; + } + enqueued_record& operator= (BOOST_RV_REF(enqueued_record) that) + { + m_timestamp = that.m_timestamp; + m_record = boost::move(that.m_record); + return *this; + } +}; + +} // namespace aux + +} // namespace sinks + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ENQUEUED_RECORD_HPP_INCLUDED_ diff --git a/boost/log/detail/event.hpp b/boost/log/detail/event.hpp new file mode 100644 index 0000000000..741ab3c9bd --- /dev/null +++ b/boost/log/detail/event.hpp @@ -0,0 +1,142 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 detail/event.hpp + * \author Andrey Semashev + * \date 24.07.2011 + */ + +#ifndef BOOST_LOG_DETAIL_EVENT_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_EVENT_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_NO_THREADS + +#if defined(BOOST_THREAD_PLATFORM_PTHREAD) +# if defined(_POSIX_SEMAPHORES) && (_POSIX_SEMAPHORES + 0) > 0 +# if defined(__GNUC__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) +# include <semaphore.h> +# include <boost/cstdint.hpp> +# define BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE +# endif +# endif +#elif defined(BOOST_THREAD_PLATFORM_WIN32) +# include <boost/cstdint.hpp> +# define BOOST_LOG_EVENT_USE_WINAPI +#endif + +#if !defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) && !defined(BOOST_LOG_EVENT_USE_WINAPI) +# include <boost/thread/mutex.hpp> +# include <boost/thread/condition_variable.hpp> +# define BOOST_LOG_EVENT_USE_BOOST_CONDITION +#endif + +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +#if defined(BOOST_LOG_EVENT_USE_POSIX_SEMAPHORE) + +class sem_based_event +{ +private: + boost::uint32_t m_state; + sem_t m_semaphore; + +public: + //! Default constructor + BOOST_LOG_API sem_based_event(); + //! Destructor + BOOST_LOG_API ~sem_based_event(); + + //! Waits for the object to become signalled + BOOST_LOG_API void wait(); + //! Sets the object to a signalled state + BOOST_LOG_API void set_signalled(); + + // Copying prohibited + BOOST_DELETED_FUNCTION(sem_based_event(sem_based_event const&)) + BOOST_DELETED_FUNCTION(sem_based_event& operator= (sem_based_event const&)) +}; + +typedef sem_based_event event; + +#elif defined(BOOST_LOG_EVENT_USE_WINAPI) + +class winapi_based_event +{ +private: + boost::uint32_t m_state; + void* m_event; + +public: + //! Default constructor + BOOST_LOG_API winapi_based_event(); + //! Destructor + BOOST_LOG_API ~winapi_based_event(); + + //! Waits for the object to become signalled + BOOST_LOG_API void wait(); + //! Sets the object to a signalled state + BOOST_LOG_API void set_signalled(); + + // Copying prohibited + BOOST_DELETED_FUNCTION(winapi_based_event(winapi_based_event const&)) + BOOST_DELETED_FUNCTION(winapi_based_event& operator= (winapi_based_event const&)) +}; + +typedef winapi_based_event event; + +#else + +class generic_event +{ +private: + boost::mutex m_mutex; + boost::condition_variable m_cond; + bool m_state; + +public: + //! Default constructor + BOOST_LOG_API generic_event(); + //! Destructor + BOOST_LOG_API ~generic_event(); + + //! Waits for the object to become signalled + BOOST_LOG_API void wait(); + //! Sets the object to a signalled state + BOOST_LOG_API void set_signalled(); + + // Copying prohibited + BOOST_DELETED_FUNCTION(generic_event(generic_event const&)) + BOOST_DELETED_FUNCTION(generic_event& operator= (generic_event const&)) +}; + +typedef generic_event event; + +#endif + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_NO_THREADS + +#endif // BOOST_LOG_DETAIL_EVENT_HPP_INCLUDED_ diff --git a/boost/log/detail/fake_mutex.hpp b/boost/log/detail/fake_mutex.hpp new file mode 100644 index 0000000000..f21f961538 --- /dev/null +++ b/boost/log/detail/fake_mutex.hpp @@ -0,0 +1,56 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 fake_mutex.hpp + * \author Andrey Semashev + * \date 31.07.2011 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_FAKE_MUTEX_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_FAKE_MUTEX_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Fake mutex that doesn't do anything. Note: we're not using \c null_mutex from Boost.Thread in order not to introduce false dependencies on Boost.Thread and Boost.Chrono. +class fake_mutex +{ +public: + BOOST_DEFAULTED_FUNCTION(fake_mutex(), {}) + void lock() {} + bool try_lock() { return true; } + template< typename T > + bool timed_lock(T const&) { return true; } + void unlock() {} + + // Copying prohibited + BOOST_DELETED_FUNCTION(fake_mutex(fake_mutex const&)) + BOOST_DELETED_FUNCTION(fake_mutex& operator=(fake_mutex const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_FAKE_MUTEX_HPP_INCLUDED_ diff --git a/boost/log/detail/footer.hpp b/boost/log/detail/footer.hpp new file mode 100644 index 0000000000..8208ebd33a --- /dev/null +++ b/boost/log/detail/footer.hpp @@ -0,0 +1,22 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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) + */ + +#if !defined(BOOST_LOG_ENABLE_WARNINGS) + +#if defined(_MSC_VER) + +#pragma warning(pop) + +#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 + +#pragma GCC diagnostic pop + +#endif + +#endif // !defined(BOOST_LOG_ENABLE_WARNINGS) + +#include <boost/config/abi_suffix.hpp> diff --git a/boost/log/detail/format.hpp b/boost/log/detail/format.hpp new file mode 100644 index 0000000000..d383aba717 --- /dev/null +++ b/boost/log/detail/format.hpp @@ -0,0 +1,336 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 format.hpp + * \author Andrey Semashev + * \date 15.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_ + +#include <string> +#include <vector> +#include <iosfwd> +#include <boost/assert.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/unhandled_exception_count.hpp> +#include <boost/log/detail/cleanup_scope_guard.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 + +namespace aux { + +//! An element (either literal or placeholder) of the format string +struct format_element +{ + //! Argument placeholder number or -1 if it's not a placeholder (i.e. a literal) + int arg_number; + //! If the element describes a constant literal, the starting character and length of the literal + unsigned int literal_start_pos, literal_len; + + format_element() : arg_number(0), literal_start_pos(0), literal_len(0) + { + } + + static format_element literal(unsigned int start_pos, unsigned int len) + { + format_element el; + el.arg_number = -1; + el.literal_start_pos = start_pos; + el.literal_len = len; + return el; + } + + static format_element positional_argument(unsigned int arg_n) + { + format_element el; + el.arg_number = arg_n; + return el; + } +}; + +//! Parsed format string description +template< typename CharT > +struct format_description +{ + BOOST_COPYABLE_AND_MOVABLE_ALT(format_description) + +public: + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + + //! Array of format element descriptors + typedef std::vector< format_element > format_element_list; + + //! Characters of all literal parts of the format string + string_type literal_chars; + //! Format element descriptors + format_element_list format_elements; + + BOOST_DEFAULTED_FUNCTION(format_description(), {}) + + format_description(format_description const& that) : literal_chars(that.literal_chars), format_elements(that.format_elements) + { + } + + format_description(BOOST_RV_REF(format_description) that) + { + literal_chars.swap(that.literal_chars); + format_elements.swap(that.format_elements); + } + + format_description& operator= (format_description that) + { + literal_chars.swap(that.literal_chars); + format_elements.swap(that.format_elements); + return *this; + } +}; + +//! Parses format string +template< typename CharT > +BOOST_LOG_API format_description< CharT > parse_format(const CharT* begin, const CharT* end); + +//! Parses format string +template< typename CharT > +BOOST_FORCEINLINE format_description< CharT > parse_format(const CharT* begin) +{ + return parse_format(begin, begin + std::char_traits< CharT >::length(begin)); +} + +//! Parses format string +template< typename CharT, typename TraitsT, typename AllocatorT > +BOOST_FORCEINLINE format_description< CharT > parse_format(std::basic_string< CharT, TraitsT, AllocatorT > const& fmt) +{ + const CharT* begin = fmt.c_str(); + return parse_format(begin, begin + fmt.size()); +} + +//! Formatter object +template< typename CharT > +class basic_format +{ +public: + //! Character type + typedef CharT char_type; + //! String type + typedef std::basic_string< char_type > string_type; + //! Stream type + typedef basic_formatting_ostream< char_type > stream_type; + //! Format description type + typedef format_description< char_type > format_description_type; + + //! The pump receives arguments and formats them into strings. At destruction the pump composes the final string in the attached stream. + class pump; + friend class pump; + +private: + //! Formatting params for a single placeholder in the format string + struct formatting_params + { + //! Formatting element index in the format description + unsigned int element_idx; + //! Formatting result + string_type target; + + formatting_params() : element_idx(~0u) {} + }; + typedef std::vector< formatting_params > formatting_params_list; + +private: + //! Format string description + format_description_type m_format; + //! Formatting parameters for all placeholders + formatting_params_list m_formatting_params; + //! Current formatting position + unsigned int m_current_idx; + +public: + //! Initializing constructor + explicit basic_format(string_type const& fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0) + { + init_params(); + } + //! Initializing constructor + explicit basic_format(const char_type* fmt) : m_format(aux::parse_format(fmt)), m_current_idx(0) + { + init_params(); + } + + //! Clears all formatted strings and resets the current formatting position + void clear() BOOST_NOEXCEPT + { + for (typename formatting_params_list::iterator it = m_formatting_params.begin(), end = m_formatting_params.end(); it != end; ++it) + { + it->target.clear(); + } + m_current_idx = 0; + } + + //! Creates a pump that will receive all format arguments and put the formatted string into the stream + pump make_pump(stream_type& strm) BOOST_NOEXCEPT + { + return pump(*this, strm); + } + + //! Composes the final string from the formatted pieces + void compose(string_type& str) const + { + typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end(); + for (; it != end; ++it) + { + if (it->arg_number >= 0) + { + // This is a placeholder + str.append(m_formatting_params[it->arg_number].target); + } + else + { + // This is a literal + const char_type* p = m_format.literal_chars.c_str() + it->literal_start_pos; + str.append(p, it->literal_len); + } + } + } + + //! Composes the final string from the formatted pieces + string_type str() const + { + string_type result; + compose(result); + return boost::move(result); + } + +private: + //! Initializes the formatting params + void init_params() + { + typename format_description_type::format_element_list::const_iterator it = m_format.format_elements.begin(), end = m_format.format_elements.end(); + for (; it != end; ++it) + { + if (it->arg_number >= 0) + { + if (static_cast< unsigned int >(it->arg_number) >= m_formatting_params.size()) + m_formatting_params.resize(it->arg_number + 1); + m_formatting_params[it->arg_number].element_idx = static_cast< unsigned int >(it - m_format.format_elements.begin()); + } + } + } +}; + +//! The pump receives arguments and formats them into strings. At destruction the pump composes the final string in the attached stream. +template< typename CharT > +class basic_format< CharT >::pump +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(pump) + +private: + //! The guard temporarily replaces storage string in the specified stream + struct scoped_storage + { + scoped_storage(stream_type& strm, string_type& storage) : m_stream(strm), m_storage_backup(*strm.rdbuf()->storage()) + { + strm.attach(storage); + } + ~scoped_storage() + { + m_stream.attach(m_storage_backup); + } + + private: + stream_type& m_stream; + string_type& m_storage_backup; + }; + +private: + //! Reference to the owner + basic_format* m_owner; + //! Reference to the stream + stream_type* m_stream; + //! Unhandled exception count + const unsigned int m_exception_count; + +public: + //! Initializing constructor + pump(basic_format& owner, stream_type& strm) BOOST_NOEXCEPT : m_owner(&owner), m_stream(&strm), m_exception_count(unhandled_exception_count()) + { + } + + //! Move constructor + pump(BOOST_RV_REF(pump) that) BOOST_NOEXCEPT : m_owner(that.m_owner), m_stream(that.m_stream), m_exception_count(that.m_exception_count) + { + that.m_owner = NULL; + that.m_stream = NULL; + } + + //! Destructor + ~pump() BOOST_NOEXCEPT_IF(false) + { + if (m_owner) + { + // Whether or not the destructor is called because of an exception, the format object has to be cleared + boost::log::aux::cleanup_guard< basic_format< char_type > > cleanup1(*m_owner); + + BOOST_ASSERT(m_stream != NULL); + if (m_exception_count >= unhandled_exception_count()) + { + // Compose the final string in the stream buffer + m_stream->flush(); + m_owner->compose(*m_stream->rdbuf()->storage()); + } + } + } + + /*! + * Puts an argument to the formatter. Note the pump has to be returned by value and not by reference in order this to + * work with Boost.Phoenix expressions. Otherwise the pump that is returned from \c basic_format::make_pump is + * destroyed after the first call to \c operator%, and the returned reference becomes dangling. + */ + template< typename T > + pump operator% (T const& val) + { + BOOST_ASSERT_MSG(m_owner != NULL && m_stream != NULL, "Boost.Log: This basic_format::pump has already been moved from"); + + if (m_owner->m_current_idx < m_owner->m_formatting_params.size()) + { + scoped_storage storage_guard(*m_stream, m_owner->m_formatting_params[m_owner->m_current_idx].target); + + *m_stream << val; + m_stream->flush(); + + ++m_owner->m_current_idx; + } + + return boost::move(*this); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_FORMAT_HPP_INCLUDED_ diff --git a/boost/log/detail/function_traits.hpp b/boost/log/detail/function_traits.hpp new file mode 100644 index 0000000000..bd298fca30 --- /dev/null +++ b/boost/log/detail/function_traits.hpp @@ -0,0 +1,236 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 function_traits.hpp + * \author Andrey Semashev + * \date 30.08.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_ + +#include <boost/mpl/has_xxx.hpp> +#include <boost/log/detail/config.hpp> + +#if defined(BOOST_NO_SFINAE) || defined(BOOST_MPL_CFG_NO_HAS_XXX) +# if !defined(BOOST_LOG_NO_FUNCTION_TRAITS) +# define BOOST_LOG_NO_FUNCTION_TRAITS +# endif +#else + +#include <boost/mpl/int.hpp> +#include <boost/mpl/front.hpp> +#include <boost/mpl/pop_front.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/function_types/function_arity.hpp> +#include <boost/function_types/parameter_types.hpp> +#include <boost/function_types/is_nonmember_callable_builtin.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + + // A number of traits to deal with functors + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_argument_type, argument_type, false) + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_first_argument_type, first_argument_type, false) + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_second_argument_type, second_argument_type, false) + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_arg1_type, arg1_type, false) + BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_arg2_type, arg2_type, false) + + namespace has_arity_no_adl { + + typedef char yes_type; + struct no_type + { + char dummy[2]; + }; + + template< typename FunT, int ArityV = FunT::arity > + struct checker + { + }; + + template< typename FunT > + yes_type has_arity_impl(FunT const&, checker< FunT >*); + template< typename FunT > + no_type has_arity_impl(FunT const&, ...); + + } // namespace has_arity_no_adl + + //! The metafunction detects if the type has an arity static constant member + template< typename FunT > + struct has_arity + { + static FunT const& get_FunT(); + + enum value_t { value = (sizeof(has_arity_no_adl::has_arity_impl(get_FunT(), 0)) == sizeof(has_arity_no_adl::yes_type)) }; + typedef mpl::bool_< value > type; + }; + + //! The metafunction results in an unqualified type with removed reference + template< typename T > + struct root_type : + public remove_cv< + typename remove_reference< + T + >::type + > + { + }; + + template< + typename FunT, + bool = function_types::is_nonmember_callable_builtin< FunT >::value, + bool = has_argument_type< FunT >::value, + bool = has_first_argument_type< FunT >::value, + bool = has_arg1_type< FunT >::value + > + struct first_argument_type_of_impl + { + }; + template< typename FunT > + struct first_argument_type_of_impl< FunT, true, false, false, false > + { + typedef typename root_type< + typename mpl::front< + typename function_types::parameter_types< FunT >::type + >::type + >::type type; + }; + template< typename FunT, bool HasFirstArgumentV, bool HasArg1V > + struct first_argument_type_of_impl< FunT, false, true, HasFirstArgumentV, HasArg1V > + { + typedef typename root_type< + typename FunT::argument_type + >::type type; + }; + template< typename FunT, bool HasArg1V > + struct first_argument_type_of_impl< FunT, false, false, true, HasArg1V > + { + typedef typename root_type< + typename FunT::first_argument_type + >::type type; + }; + template< typename FunT > + struct first_argument_type_of_impl< FunT, false, false, false, true > + { + typedef typename root_type< + typename FunT::arg1_type + >::type type; + }; + + //! The metafunction returns the first argument type of a function + template< typename FunT > + struct first_argument_type_of : + public first_argument_type_of_impl< FunT > + { + }; + + + template< + typename FunT, + bool = function_types::is_nonmember_callable_builtin< FunT >::value, + bool = has_second_argument_type< FunT >::value, + bool = has_arg2_type< FunT >::value + > + struct second_argument_type_of_impl + { + }; + template< typename FunT > + struct second_argument_type_of_impl< FunT, true, false, false > + { + typedef typename root_type< + typename mpl::front< + typename mpl::pop_front< + typename function_types::parameter_types< FunT >::type + >::type + >::type + >::type type; + }; + template< typename FunT, bool HasArg2V > + struct second_argument_type_of_impl< FunT, false, true, HasArg2V > + { + typedef typename root_type< + typename FunT::second_argument_type + >::type type; + }; + template< typename FunT > + struct second_argument_type_of_impl< FunT, false, false, true > + { + typedef typename root_type< + typename FunT::arg2_type + >::type type; + }; + + //! The metafunction returns the second argument type of a function + template< typename FunT > + struct second_argument_type_of : + public second_argument_type_of_impl< FunT > + { + }; + + + template< + typename FunT, + bool = function_types::is_nonmember_callable_builtin< FunT >::value, + bool = has_arity< FunT >::value, + bool = has_argument_type< FunT >::value, + bool = has_second_argument_type< FunT >::value + > + struct arity_of_impl + { + }; + template< typename FunT > + struct arity_of_impl< FunT, true, false, false, false > : + public function_types::function_arity< FunT > + { + }; + template< typename FunT, bool HasArgumentTypeV, bool HasSecondArgumentTypeV > + struct arity_of_impl< FunT, false, true, HasArgumentTypeV, HasSecondArgumentTypeV > : + public mpl::int_< FunT::arity > + { + }; + template< typename FunT, bool HasArgumentTypeV > + struct arity_of_impl< FunT, false, false, HasArgumentTypeV, true > : + public mpl::int_< 2 > + { + }; + template< typename FunT > + struct arity_of_impl< FunT, false, false, true, false > : + public mpl::int_< 1 > + { + }; + + //! The metafunction returns the arity of a function + template< typename FunT > + struct arity_of : + public arity_of_impl< FunT > + { + }; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // defined(BOOST_NO_SFINAE) || defined(BOOST_MPL_CFG_NO_HAS_XXX) + +#endif // BOOST_LOG_DETAIL_FUNCTION_TRAITS_HPP_INCLUDED_ diff --git a/boost/log/detail/generate_overloads.hpp b/boost/log/detail/generate_overloads.hpp new file mode 100644 index 0000000000..63b9edf081 --- /dev/null +++ b/boost/log/detail/generate_overloads.hpp @@ -0,0 +1,30 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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) + */ + +BOOST_LOG_AUX_OVERLOAD(const&, const&) +BOOST_LOG_AUX_OVERLOAD(&, const&) +BOOST_LOG_AUX_OVERLOAD(const&, &) +BOOST_LOG_AUX_OVERLOAD(&, &) + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +BOOST_LOG_AUX_OVERLOAD(const&&, const&&) +BOOST_LOG_AUX_OVERLOAD(&&, const&&) +BOOST_LOG_AUX_OVERLOAD(const&&, &&) +BOOST_LOG_AUX_OVERLOAD(&&, &&) + +BOOST_LOG_AUX_OVERLOAD(const&&, const&) +BOOST_LOG_AUX_OVERLOAD(&&, const&) +BOOST_LOG_AUX_OVERLOAD(const&&, &) +BOOST_LOG_AUX_OVERLOAD(&&, &) + +BOOST_LOG_AUX_OVERLOAD(const&, const&&) +BOOST_LOG_AUX_OVERLOAD(&, const&&) +BOOST_LOG_AUX_OVERLOAD(const&, &&) +BOOST_LOG_AUX_OVERLOAD(&, &&) + +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) diff --git a/boost/log/detail/header.hpp b/boost/log/detail/header.hpp new file mode 100644 index 0000000000..f7cf75d557 --- /dev/null +++ b/boost/log/detail/header.hpp @@ -0,0 +1,64 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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) + */ + +#include <boost/config/abi_prefix.hpp> + +#if !defined(BOOST_LOG_ENABLE_WARNINGS) + +#if defined(_MSC_VER) + +#pragma warning(push, 3) +// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B' +#pragma warning(disable: 4251) +// non dll-interface class 'A' used as base for dll-interface class 'B' +#pragma warning(disable: 4275) +// switch statement contains 'default' but no 'case' labels +#pragma warning(disable: 4065) +// 'this' : used in base member initializer list +#pragma warning(disable: 4355) +// 'int' : forcing value to bool 'true' or 'false' (performance warning) +#pragma warning(disable: 4800) +// unreferenced formal parameter +#pragma warning(disable: 4100) +// conditional expression is constant +#pragma warning(disable: 4127) +// default constructor could not be generated +#pragma warning(disable: 4510) +// copy constructor could not be generated +#pragma warning(disable: 4511) +// assignment operator could not be generated +#pragma warning(disable: 4512) +// struct 'A' can never be instantiated - user defined constructor required +#pragma warning(disable: 4610) +// function marked as __forceinline not inlined +#pragma warning(disable: 4714) +// decorated name length exceeded, name was truncated +#pragma warning(disable: 4503) +// declaration of 'A' hides previous local declaration +#pragma warning(disable: 4456) +// declaration of 'A' hides global declaration +#pragma warning(disable: 4459) + +#elif defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \ + && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 + +#pragma GCC diagnostic push +// 'var' defined but not used +#pragma GCC diagnostic ignored "-Wunused-variable" +// unused parameter 'arg' +#pragma GCC diagnostic ignored "-Wunused-parameter" +// missing initializer for member var +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" + +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 +// typedef 'foo' locally defined but not used +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#endif + +#endif + +#endif // !defined(BOOST_LOG_ENABLE_WARNINGS) diff --git a/boost/log/detail/id.hpp b/boost/log/detail/id.hpp new file mode 100644 index 0000000000..2ca1e1e30d --- /dev/null +++ b/boost/log/detail/id.hpp @@ -0,0 +1,84 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 id.hpp + * \author Andrey Semashev + * \date 08.01.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_ID_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_ID_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Generic identifier class +template< typename DescriptorT > +class id +{ +public: + //! Native type of the process id + typedef typename DescriptorT::native_type native_type; + +private: + native_type m_NativeID; + +public: + BOOST_CONSTEXPR id() BOOST_NOEXCEPT : m_NativeID(0) {} + + explicit id(native_type native) BOOST_NOEXCEPT : m_NativeID(native) {} + + native_type native_id() const BOOST_NOEXCEPT { return m_NativeID; } + + bool operator== (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID == that.m_NativeID); + } + bool operator!= (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID != that.m_NativeID); + } + bool operator< (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID < that.m_NativeID); + } + bool operator> (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID > that.m_NativeID); + } + bool operator<= (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID <= that.m_NativeID); + } + bool operator>= (id const& that) const BOOST_NOEXCEPT + { + return (m_NativeID >= that.m_NativeID); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_ID_HPP_INCLUDED_ diff --git a/boost/log/detail/light_function.hpp b/boost/log/detail/light_function.hpp new file mode 100644 index 0000000000..b673359e63 --- /dev/null +++ b/boost/log/detail/light_function.hpp @@ -0,0 +1,521 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 light_function.hpp + * \author Andrey Semashev + * \date 20.06.2010 + * + * \brief This header is the Boost.Log library impl, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + * + * The file contains a lightweight alternative of Boost.Function. It does not provide all + * features of Boost.Function but doesn't introduce dependency on Boost.Bind. + */ + +#ifndef BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_ + +#include <cstddef> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/type_traits/remove_cv.hpp> +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/preprocessor/iteration/iterate.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> +#endif +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#include <boost/utility/enable_if.hpp> +#else +#include <boost/type_traits/remove_reference.hpp> +#endif +#if defined(BOOST_NO_CXX11_NULLPTR) +#include <boost/assert.hpp> +#endif +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_LIGHT_FUNCTION_LIMIT +#define BOOST_LOG_LIGHT_FUNCTION_LIMIT 2 +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template< typename T, typename ThisT > +struct is_cv_same { enum _ { value = false }; }; +template< typename T > +struct is_cv_same< T, T > { enum _ { value = true }; }; +template< typename T > +struct is_cv_same< T, const T > { enum _ { value = true }; }; +template< typename T > +struct is_cv_same< T, volatile T > { enum _ { value = true }; }; +template< typename T > +struct is_cv_same< T, const volatile T > { enum _ { value = true }; }; + +template< typename T, typename ThisT > +struct is_rv_or_same { enum _ { value = false }; }; +template< typename T > +struct is_rv_or_same< T, T > { enum _ { value = true }; }; +template< typename T, typename ThisT > +struct is_rv_or_same< boost::rv< T >, ThisT > { enum _ { value = true }; }; + +#endif + +template< typename SignatureT > +class light_function; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template< typename ResultT, typename... ArgsT > +class light_function< ResultT (ArgsT...) > +{ + typedef light_function this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + typedef ResultT result_type; + +private: + struct impl_base + { + typedef result_type (*invoke_type)(void*, ArgsT...); + const invoke_type invoke; + + typedef impl_base* (*clone_type)(const void*); + const clone_type clone; + + typedef void (*destroy_type)(void*); + const destroy_type destroy; + + impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) + { + } + + BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) + BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) + }; + +#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) + template< typename FunT > + class impl; + template< typename FunT > + friend class impl; +#endif + + template< typename FunT > + class impl : + public impl_base + { + typedef impl< FunT > this_type; + + FunT m_Function; + + public: + explicit impl(FunT const& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(fun) + { + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + explicit impl(FunT&& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(boost::move(fun)) + { + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + static void destroy_impl(void* self) + { + delete static_cast< impl* >(static_cast< impl_base* >(self)); + } + static impl_base* clone_impl(const void* self) + { + return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); + } + static result_type invoke_impl(void* self, ArgsT... args) + { + return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...); + } + + BOOST_DELETED_FUNCTION(impl(impl const&)) + BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) + }; + +private: + impl_base* m_pImpl; + +public: + BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) + { + } + light_function(this_type const& that) + { + if (that.m_pImpl) + m_pImpl = that.m_pImpl->clone(that.m_pImpl); + else + m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + that.m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + ((this_type&)that).m_pImpl = NULL; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function(FunT&& fun) : + m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) + { + } +#else + template< typename FunT > + light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< FunT >(fun)) + { + } + template< typename FunT > + light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) + { + } +#endif + + //! Constructor from NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT +#else + BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT +#endif + : m_pImpl(NULL) + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + } + ~light_function() + { + clear(); + } + + light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) + { + light_function tmp = static_cast< this_type const& >(that); + this->swap(tmp); + return *this; + } + //! Assignment of NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + light_function& operator= (std::nullptr_t) +#else + light_function& operator= (int p) +#endif + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + clear(); + return *this; + } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function& operator= (FunT&& fun) + { + light_function tmp(boost::forward< FunT >(fun)); + this->swap(tmp); + return *this; + } +#else + template< typename FunT > + typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type + operator= (FunT const& fun) + { + light_function tmp(fun); + this->swap(tmp); + return *this; + } +#endif + + result_type operator() (ArgsT... args) const + { + return m_pImpl->invoke(m_pImpl, args...); + } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + void clear() BOOST_NOEXCEPT + { + if (m_pImpl) + { + m_pImpl->destroy(m_pImpl); + m_pImpl = NULL; + } + } + + void swap(this_type& that) BOOST_NOEXCEPT + { + impl_base* p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } +}; + +template< typename... ArgsT > +class light_function< void (ArgsT...) > +{ + typedef light_function this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + typedef void result_type; + +private: + struct impl_base + { + typedef void (*invoke_type)(void*, ArgsT...); + const invoke_type invoke; + + typedef impl_base* (*clone_type)(const void*); + const clone_type clone; + + typedef void (*destroy_type)(void*); + const destroy_type destroy; + + impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) + { + } + + BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) + BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) + }; + +#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) + template< typename FunT > + class impl; + template< typename FunT > + friend class impl; +#endif + + template< typename FunT > + class impl : + public impl_base + { + typedef impl< FunT > this_type; + + FunT m_Function; + + public: + explicit impl(FunT const& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(fun) + { + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + explicit impl(FunT&& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(boost::move(fun)) + { + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + static void destroy_impl(void* self) + { + delete static_cast< impl* >(static_cast< impl_base* >(self)); + } + static impl_base* clone_impl(const void* self) + { + return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); + } + static result_type invoke_impl(void* self, ArgsT... args) + { + static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(args...); + } + + BOOST_DELETED_FUNCTION(impl(impl const&)) + BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) + }; + +private: + impl_base* m_pImpl; + +public: + BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) + { + } + light_function(this_type const& that) + { + if (that.m_pImpl) + m_pImpl = that.m_pImpl->clone(that.m_pImpl); + else + m_pImpl = NULL; + } + light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + that.m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + ((this_type&)that).m_pImpl = NULL; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function(FunT&& fun) : + m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) + { + } +#else + template< typename FunT > + light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< FunT >(fun)) + { + } + template< typename FunT > + light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) + { + } +#endif + + //! Constructor from NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT +#else + BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT +#endif + : m_pImpl(NULL) + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + } + ~light_function() + { + clear(); + } + + light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) + { + light_function tmp = static_cast< this_type const& >(that); + this->swap(tmp); + return *this; + } + //! Assignment of NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + light_function& operator= (std::nullptr_t) +#else + light_function& operator= (int p) +#endif + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + clear(); + return *this; + } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function& operator= (FunT&& fun) + { + light_function tmp(boost::forward< FunT >(fun)); + this->swap(tmp); + return *this; + } +#else + template< typename FunT > + typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type + operator= (FunT const& fun) + { + light_function tmp(fun); + this->swap(tmp); + return *this; + } +#endif + + result_type operator() (ArgsT... args) const + { + m_pImpl->invoke(m_pImpl, args...); + } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + void clear() BOOST_NOEXCEPT + { + if (m_pImpl) + { + m_pImpl->destroy(m_pImpl); + m_pImpl = NULL; + } + } + + void swap(this_type& that) BOOST_NOEXCEPT + { + impl_base* p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } +}; + +#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#define BOOST_PP_FILENAME_1 <boost/log/detail/light_function_pp.hpp> +#define BOOST_PP_ITERATION_LIMITS (0, BOOST_LOG_LIGHT_FUNCTION_LIMIT) +#include BOOST_PP_ITERATE() + +#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template< typename SignatureT > +inline void swap(light_function< SignatureT >& left, light_function< SignatureT >& right) +{ + left.swap(right); +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_LIGHT_FUNCTION_HPP_INCLUDED_ diff --git a/boost/log/detail/light_function_pp.hpp b/boost/log/detail/light_function_pp.hpp new file mode 100644 index 0000000000..55eca7cdd8 --- /dev/null +++ b/boost/log/detail/light_function_pp.hpp @@ -0,0 +1,424 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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) + */ + +template< + typename ResultT + BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename ArgT) +> +class light_function< ResultT (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) > +{ + typedef light_function this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + typedef ResultT result_type; + +private: + struct impl_base + { + typedef result_type (*invoke_type)(void* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT)); + const invoke_type invoke; + + typedef impl_base* (*clone_type)(const void*); + const clone_type clone; + + typedef void (*destroy_type)(void*); + const destroy_type destroy; + + impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) + { + } + + BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) + BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) + }; + +#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) + template< typename FunT > + class impl; + template< typename FunT > + friend class impl; +#endif + + template< typename FunT > + class impl : + public impl_base + { + typedef impl< FunT > this_type; + + FunT m_Function; + + public: + explicit impl(FunT const& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(fun) + { + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + explicit impl(FunT&& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(boost::move(fun)) + { + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + static void destroy_impl(void* self) + { + delete static_cast< impl* >(static_cast< impl_base* >(self)); + } + static impl_base* clone_impl(const void* self) + { + return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); + } + static result_type invoke_impl(void* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) + { + return static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)); + } + + BOOST_DELETED_FUNCTION(impl(impl const&)) + BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) + }; + +private: + impl_base* m_pImpl; + +public: + BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) + { + } + light_function(this_type const& that) + { + if (that.m_pImpl) + m_pImpl = that.m_pImpl->clone(that.m_pImpl); + else + m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + that.m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + ((this_type&)that).m_pImpl = NULL; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function(FunT&& fun) : + m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) + { + } +#else + template< typename FunT > + light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< FunT >(fun)) + { + } + template< typename FunT > + light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) + { + } +#endif + + //! Constructor from NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT +#else + BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT +#endif + : m_pImpl(NULL) + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + } + ~light_function() + { + clear(); + } + + light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) + { + light_function tmp = static_cast< this_type const& >(that); + this->swap(tmp); + return *this; + } + //! Assignment of NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + light_function& operator= (std::nullptr_t) +#else + light_function& operator= (int p) +#endif + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + clear(); + return *this; + } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function& operator= (FunT&& fun) + { + light_function tmp(boost::forward< FunT >(fun)); + this->swap(tmp); + return *this; + } +#else + template< typename FunT > + typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type + operator= (FunT const& fun) + { + light_function tmp(fun); + this->swap(tmp); + return *this; + } +#endif + + result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const + { + return m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg)); + } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + void clear() BOOST_NOEXCEPT + { + if (m_pImpl) + { + m_pImpl->destroy(m_pImpl); + m_pImpl = NULL; + } + } + + void swap(this_type& that) BOOST_NOEXCEPT + { + impl_base* p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } +}; + +template< + BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) +> +class light_function< void (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT)) > +{ + typedef light_function this_type; + BOOST_COPYABLE_AND_MOVABLE(this_type) + +public: + typedef void result_type; + +private: + struct impl_base + { + typedef void (*invoke_type)(void* BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), ArgT)); + const invoke_type invoke; + + typedef impl_base* (*clone_type)(const void*); + const clone_type clone; + + typedef void (*destroy_type)(void*); + const destroy_type destroy; + + impl_base(invoke_type inv, clone_type cl, destroy_type dstr) : invoke(inv), clone(cl), destroy(dstr) + { + } + + BOOST_DELETED_FUNCTION(impl_base(impl_base const&)) + BOOST_DELETED_FUNCTION(impl_base& operator= (impl_base const&)) + }; + +#if !defined(BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS) + template< typename FunT > + class impl; + template< typename FunT > + friend class impl; +#endif + + template< typename FunT > + class impl : + public impl_base + { + typedef impl< FunT > this_type; + + FunT m_Function; + + public: + explicit impl(FunT const& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(fun) + { + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + explicit impl(FunT&& fun) : + impl_base(&this_type::invoke_impl, &this_type::clone_impl, &this_type::destroy_impl), + m_Function(boost::move(fun)) + { + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + static void destroy_impl(void* self) + { + delete static_cast< impl* >(static_cast< impl_base* >(self)); + } + static impl_base* clone_impl(const void* self) + { + return new impl(static_cast< const impl* >(static_cast< const impl_base* >(self))->m_Function); + } + static result_type invoke_impl(void* self BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) + { + static_cast< impl* >(static_cast< impl_base* >(self))->m_Function(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg)); + } + + BOOST_DELETED_FUNCTION(impl(impl const&)) + BOOST_DELETED_FUNCTION(impl& operator= (impl const&)) + }; + +private: + impl_base* m_pImpl; + +public: + BOOST_CONSTEXPR light_function() BOOST_NOEXCEPT : m_pImpl(NULL) + { + } + light_function(this_type const& that) + { + if (that.m_pImpl) + m_pImpl = that.m_pImpl->clone(that.m_pImpl); + else + m_pImpl = NULL; + } + light_function(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + that.m_pImpl = NULL; + } + + light_function(BOOST_RV_REF(const this_type) that) BOOST_NOEXCEPT + { + m_pImpl = that.m_pImpl; + ((this_type&)that).m_pImpl = NULL; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function(FunT&& fun) : + m_pImpl(new impl< typename remove_cv< typename remove_reference< FunT >::type >::type >(boost::forward< FunT >(fun))) + { + } +#else + template< typename FunT > + light_function(FunT const& fun, typename disable_if_c< is_rv_or_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< FunT >(fun)) + { + } + template< typename FunT > + light_function(BOOST_RV_REF(FunT) fun, typename disable_if_c< is_cv_same< FunT, this_type >::value, int >::type = 0) : + m_pImpl(new impl< typename remove_cv< FunT >::type >(fun)) + { + } +#endif + + //! Constructor from NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + BOOST_CONSTEXPR light_function(std::nullptr_t) BOOST_NOEXCEPT +#else + BOOST_CONSTEXPR light_function(int p) BOOST_NOEXCEPT +#endif + : m_pImpl(NULL) + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + } + ~light_function() + { + clear(); + } + + light_function& operator= (BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + light_function& operator= (BOOST_COPY_ASSIGN_REF(this_type) that) + { + light_function tmp = static_cast< this_type const& >(that); + this->swap(tmp); + return *this; + } + //! Assignment of NULL +#if !defined(BOOST_NO_CXX11_NULLPTR) + light_function& operator= (std::nullptr_t) +#else + light_function& operator= (int p) +#endif + { +#if defined(BOOST_NO_CXX11_NULLPTR) + BOOST_ASSERT(p == 0); +#endif + clear(); + return *this; + } +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template< typename FunT > + light_function& operator= (FunT&& fun) + { + light_function tmp(boost::forward< FunT >(fun)); + this->swap(tmp); + return *this; + } +#else + template< typename FunT > + typename disable_if_c< is_rv_or_same< FunT, this_type >::value, this_type& >::type + operator= (FunT const& fun) + { + light_function tmp(fun); + this->swap(tmp); + return *this; + } +#endif + + result_type operator() (BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, arg)) const + { + m_pImpl->invoke(m_pImpl BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), arg)); + } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + bool operator! () const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + bool empty() const BOOST_NOEXCEPT { return (m_pImpl == NULL); } + void clear() BOOST_NOEXCEPT + { + if (m_pImpl) + { + m_pImpl->destroy(m_pImpl); + m_pImpl = NULL; + } + } + + void swap(this_type& that) BOOST_NOEXCEPT + { + impl_base* p = m_pImpl; + m_pImpl = that.m_pImpl; + that.m_pImpl = p; + } +}; diff --git a/boost/log/detail/light_rw_mutex.hpp b/boost/log/detail/light_rw_mutex.hpp new file mode 100644 index 0000000000..abfef13972 --- /dev/null +++ b/boost/log/detail/light_rw_mutex.hpp @@ -0,0 +1,208 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 light_rw_mutex.hpp + * \author Andrey Semashev + * \date 24.03.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_LIGHT_RW_MUTEX_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_LIGHT_RW_MUTEX_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_NO_THREADS + +#include <boost/log/detail/header.hpp> + +#if defined(BOOST_THREAD_POSIX) // This one can be defined by users, so it should go first +#define BOOST_LOG_LWRWMUTEX_USE_PTHREAD +#elif defined(BOOST_WINDOWS) && defined(BOOST_LOG_USE_WINNT6_API) +#define BOOST_LOG_LWRWMUTEX_USE_SRWLOCK +#elif defined(BOOST_HAS_PTHREADS) +#define BOOST_LOG_LWRWMUTEX_USE_PTHREAD +#endif + +#if defined(BOOST_LOG_LWRWMUTEX_USE_SRWLOCK) + +#if defined(BOOST_USE_WINDOWS_H) + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 // _WIN32_WINNT_LONGHORN +#endif + +#include <windows.h> + +#else // defined(BOOST_USE_WINDOWS_H) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +extern "C" { + +struct SRWLOCK { void* p; }; +__declspec(dllimport) void __stdcall InitializeSRWLock(SRWLOCK*); +__declspec(dllimport) void __stdcall ReleaseSRWLockExclusive(SRWLOCK*); +__declspec(dllimport) void __stdcall ReleaseSRWLockShared(SRWLOCK*); +__declspec(dllimport) void __stdcall AcquireSRWLockExclusive(SRWLOCK*); +__declspec(dllimport) void __stdcall AcquireSRWLockShared(SRWLOCK*); + +} // extern "C" + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_USE_WINDOWS_H + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A light read/write mutex that uses WinNT 6 and later APIs +class light_rw_mutex +{ + SRWLOCK m_Mutex; + +public: + light_rw_mutex() + { + InitializeSRWLock(&m_Mutex); + } + void lock_shared() + { + AcquireSRWLockShared(&m_Mutex); + } + void unlock_shared() + { + ReleaseSRWLockShared(&m_Mutex); + } + void lock() + { + AcquireSRWLockExclusive(&m_Mutex); + } + void unlock() + { + ReleaseSRWLockExclusive(&m_Mutex); + } + + // Noncopyable + BOOST_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&)) + BOOST_DELETED_FUNCTION(light_rw_mutex& operator= (light_rw_mutex const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#elif defined(BOOST_LOG_LWRWMUTEX_USE_PTHREAD) + +#include <pthread.h> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A light read/write mutex that maps directly onto POSIX threading library +class light_rw_mutex +{ + pthread_rwlock_t m_Mutex; + +public: + light_rw_mutex() + { + pthread_rwlock_init(&m_Mutex, NULL); + } + ~light_rw_mutex() + { + pthread_rwlock_destroy(&m_Mutex); + } + void lock_shared() + { + pthread_rwlock_rdlock(&m_Mutex); + } + void unlock_shared() + { + pthread_rwlock_unlock(&m_Mutex); + } + void lock() + { + pthread_rwlock_wrlock(&m_Mutex); + } + void unlock() + { + pthread_rwlock_unlock(&m_Mutex); + } + + // Noncopyable + BOOST_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&)) + BOOST_DELETED_FUNCTION(light_rw_mutex& operator= (light_rw_mutex const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#else + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A light read/write mutex +class light_rw_mutex +{ + struct { void* p; } m_Mutex; + +public: + BOOST_LOG_API light_rw_mutex(); + BOOST_LOG_API ~light_rw_mutex(); + BOOST_LOG_API void lock_shared(); + BOOST_LOG_API void unlock_shared(); + BOOST_LOG_API void lock(); + BOOST_LOG_API void unlock(); + + // Noncopyable + BOOST_DELETED_FUNCTION(light_rw_mutex(light_rw_mutex const&)) + BOOST_DELETED_FUNCTION(light_rw_mutex& operator= (light_rw_mutex const&)) +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_NO_THREADS + +#endif // BOOST_LOG_DETAIL_LIGHT_RW_MUTEX_HPP_INCLUDED_ diff --git a/boost/log/detail/locking_ptr.hpp b/boost/log/detail/locking_ptr.hpp new file mode 100644 index 0000000000..913780e98e --- /dev/null +++ b/boost/log/detail/locking_ptr.hpp @@ -0,0 +1,148 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 locking_ptr.hpp + * \author Andrey Semashev + * \date 15.07.2009 + * + * This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_ + +#include <cstddef> +#include <boost/move/core.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/thread/lock_options.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/utility/explicit_operator_bool.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A pointer type that locks the backend until it's destroyed +template< typename T, typename LockableT > +class locking_ptr +{ + typedef locking_ptr this_type; + BOOST_COPYABLE_AND_MOVABLE_ALT(this_type) + +public: + //! Pointed type + typedef T element_type; + +private: + //! Lockable type + typedef LockableT lockable_type; + +private: + //! The pointer to the backend + shared_ptr< element_type > m_pElement; + //! Reference to the shared lock control object + lockable_type* m_pLock; + +public: + //! Default constructor + locking_ptr() BOOST_NOEXCEPT : m_pLock(NULL) + { + } + //! Constructor + locking_ptr(shared_ptr< element_type > const& p, lockable_type& l) : m_pElement(p), m_pLock(&l) + { + m_pLock->lock(); + } + //! Constructor + locking_ptr(shared_ptr< element_type > const& p, lockable_type& l, try_to_lock_t const&) : m_pElement(p), m_pLock(&l) + { + if (!m_pLock->try_lock()) + { + m_pElement.reset(); + m_pLock = NULL; + } + } + //! Copy constructor + locking_ptr(locking_ptr const& that) : m_pElement(that.m_pElement), m_pLock(that.m_pLock) + { + if (m_pLock) + m_pLock->lock(); + } + //! Move constructor + locking_ptr(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT : m_pLock(that.m_pLock) + { + m_pElement.swap(that.m_pElement); + that.m_pLock = NULL; + } + + //! Destructor + ~locking_ptr() + { + if (m_pLock) + m_pLock->unlock(); + } + + //! Assignment + locking_ptr& operator= (locking_ptr that) BOOST_NOEXCEPT + { + this->swap(that); + return *this; + } + + //! Indirection + element_type* operator-> () const BOOST_NOEXCEPT { return m_pElement.get(); } + //! Dereferencing + element_type& operator* () const BOOST_NOEXCEPT { return *m_pElement; } + + //! Accessor to the raw pointer + element_type* get() const BOOST_NOEXCEPT { return m_pElement.get(); } + + //! Checks for null pointer + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + //! Checks for null pointer + bool operator! () const BOOST_NOEXCEPT { return !m_pElement; } + + //! Swaps two pointers + void swap(locking_ptr& that) BOOST_NOEXCEPT + { + m_pElement.swap(that.m_pElement); + lockable_type* p = m_pLock; + m_pLock = that.m_pLock; + that.m_pLock = p; + } +}; + +//! Free raw pointer getter to assist generic programming +template< typename T, typename LockableT > +inline T* get_pointer(locking_ptr< T, LockableT > const& p) BOOST_NOEXCEPT +{ + return p.get(); +} +//! Free swap operation +template< typename T, typename LockableT > +inline void swap(locking_ptr< T, LockableT >& left, locking_ptr< T, LockableT >& right) BOOST_NOEXCEPT +{ + left.swap(right); +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_LOCKING_PTR_HPP_INCLUDED_ diff --git a/boost/log/detail/locks.hpp b/boost/log/detail/locks.hpp new file mode 100644 index 0000000000..72b8945b26 --- /dev/null +++ b/boost/log/detail/locks.hpp @@ -0,0 +1,180 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 locks.hpp + * \author Andrey Semashev + * \date 30.05.2010 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +#ifndef BOOST_LOG_NO_THREADS + +// Forward declaration of Boost.Thread locks. Specified here to avoid including Boost.Thread, +// which would bring in many dependent headers, including a great deal of Boost.DateTime. +template< typename > +class lock_guard; +template< typename > +class shared_lock; +template< typename > +class upgrade_lock; +template< typename > +class unique_lock; + +template< typename > +struct is_mutex_type; + +#endif // BOOST_LOG_NO_THREADS + +BOOST_LOG_OPEN_NAMESPACE + +//! An auxiliary pseudo-lock to express no locking requirements in logger features +template< typename MutexT > +class no_lock +{ +public: + /*! + * Constructs the pseudo-lock. The mutex is not affected during the construction. + */ + explicit no_lock(MutexT&) {} + +private: + no_lock(no_lock const&); + no_lock& operator= (no_lock const&); +}; + +namespace aux { + +#ifndef BOOST_LOG_NO_THREADS + +//! A trait to detect if the mutex supports exclusive locking +template< typename MutexT > +struct is_exclusively_lockable +{ + typedef char true_type; + struct false_type { char t[2]; }; + + template< typename T > + static true_type check_lockable(T*, void (T::*)() = &T::lock, void (T::*)() = &T::unlock); + static false_type check_lockable(void*); + + enum value_t { value = sizeof(check_lockable((MutexT*)NULL)) == sizeof(true_type) }; +}; + +//! A trait to detect if the mutex supports shared locking +template< typename MutexT > +struct is_shared_lockable +{ + typedef char true_type; + struct false_type { char t[2]; }; + + template< typename T > + static true_type check_shared_lockable(T*, void (T::*)() = &T::lock_shared, void (T::*)() = &T::unlock_shared); + static false_type check_shared_lockable(void*); + + enum value_t { value = sizeof(check_shared_lockable((MutexT*)NULL)) == sizeof(true_type) }; +}; + +//! An analogue to the minimalistic \c lock_guard template. Defined here to avoid including Boost.Thread. +template< typename MutexT > +struct exclusive_lock_guard +{ + explicit exclusive_lock_guard(MutexT& m) : m_Mutex(m) + { + m.lock(); + } + ~exclusive_lock_guard() + { + m_Mutex.unlock(); + } + +private: + exclusive_lock_guard(exclusive_lock_guard const&); + exclusive_lock_guard& operator= (exclusive_lock_guard const&); + +private: + MutexT& m_Mutex; +}; + +//! An analogue to the minimalistic \c lock_guard template that locks \c shared_mutex with shared ownership. +template< typename MutexT > +struct shared_lock_guard +{ + explicit shared_lock_guard(MutexT& m) : m_Mutex(m) + { + m.lock_shared(); + } + ~shared_lock_guard() + { + m_Mutex.unlock_shared(); + } + +private: + shared_lock_guard(shared_lock_guard const&); + shared_lock_guard& operator= (shared_lock_guard const&); + +private: + MutexT& m_Mutex; +}; + +//! A deadlock-safe lock type that exclusively locks two mutexes +template< typename MutexT1, typename MutexT2 > +class multiple_unique_lock2 +{ +public: + multiple_unique_lock2(MutexT1& m1, MutexT2& m2) : + m_p1(&m1), + m_p2(&m2) + { + // Yes, it's not conforming, but it works + // and it doesn't require to #include <functional> + if (static_cast< void* >(m_p1) < static_cast< void* >(m_p2)) + { + m_p1->lock(); + m_p2->lock(); + } + else + { + m_p2->lock(); + m_p1->lock(); + } + } + ~multiple_unique_lock2() + { + m_p2->unlock(); + m_p1->unlock(); + } + +private: + MutexT1* m_p1; + MutexT2* m_p2; +}; + +#endif // BOOST_LOG_NO_THREADS + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_LOCKS_HPP_INCLUDED_ diff --git a/boost/log/detail/named_scope_fmt_pp.hpp b/boost/log/detail/named_scope_fmt_pp.hpp new file mode 100644 index 0000000000..d9f0027f86 --- /dev/null +++ b/boost/log/detail/named_scope_fmt_pp.hpp @@ -0,0 +1,82 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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) + */ + +template< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) > +BOOST_FORCEINLINE format_named_scope_actor< + fallback_to_none, + typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type +> format_named_scope(attribute_name const& name, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, const& arg)) +{ + typedef typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type char_type; + return aux::format_named_scope< char_type, phoenix::actor >(name, fallback_to_none(), (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg))); +} + +template< typename DescriptorT, template< typename > class ActorT, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) > +BOOST_FORCEINLINE format_named_scope_actor< + fallback_to_none, + typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type, + ActorT +> +format_named_scope(attribute_keyword< DescriptorT, ActorT > const& keyword, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, const& arg)) +{ + BOOST_STATIC_ASSERT_MSG((is_same< typename DescriptorT::value_type, attributes::named_scope::value_type >::value),\ + "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type."); + + typedef typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type char_type; + return aux::format_named_scope< char_type, ActorT >(keyword.get_name(), fallback_to_none(), (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg))); +} + +template< typename T, typename FallbackPolicyT, typename TagT, template< typename > class ActorT, BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), typename ArgT) > +BOOST_FORCEINLINE format_named_scope_actor< + FallbackPolicyT, + typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type, + ActorT +> +format_named_scope(attribute_actor< T, FallbackPolicyT, TagT, ActorT > const& placeholder, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), ArgT, const& arg)) +{ + BOOST_STATIC_ASSERT_MSG((is_same< T, attributes::named_scope::value_type >::value),\ + "Boost.Log: Named scope formatter only accepts attribute values of type attributes::named_scope::value_type."); + + typedef typename boost::log::aux::deduce_char_type< + typename parameter::binding< + typename boost::log::aux::make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), ArgT) >::type, + keywords::tag::format, + void + >::type + >::type char_type; + return aux::format_named_scope< char_type, ActorT >(placeholder.get_name(), placeholder.get_fallback_policy(), (BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), arg))); +} diff --git a/boost/log/detail/native_typeof.hpp b/boost/log/detail/native_typeof.hpp new file mode 100644 index 0000000000..276b2942e8 --- /dev/null +++ b/boost/log/detail/native_typeof.hpp @@ -0,0 +1,63 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 native_typeof.hpp + * \author Andrey Semashev + * \date 08.03.2009 + * + * This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_NO_CXX11_DECLTYPE) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename T > +T get_root_type(T const&); + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#define BOOST_LOG_TYPEOF(x) decltype(::boost::log::aux::get_root_type(x)) + +#elif defined(__COMO__) && defined(__GNUG__) + +#define BOOST_LOG_TYPEOF(x) typeof(x) + +#elif defined(__GNUC__) || defined(__MWERKS__) + +#define BOOST_LOG_TYPEOF(x) __typeof__(x) + +#endif + + +#if !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) +#define BOOST_LOG_AUTO(var, expr) auto var = (expr) +#endif + +#if !defined(BOOST_LOG_AUTO) && defined(BOOST_LOG_TYPEOF) +#define BOOST_LOG_AUTO(var, expr) BOOST_LOG_TYPEOF((expr)) var = (expr) +#endif + +#endif // BOOST_LOG_DETAIL_NATIVE_TYPEOF_HPP_INCLUDED_ diff --git a/boost/log/detail/parameter_tools.hpp b/boost/log/detail/parameter_tools.hpp new file mode 100644 index 0000000000..692a3377d3 --- /dev/null +++ b/boost/log/detail/parameter_tools.hpp @@ -0,0 +1,114 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 parameter_tools.hpp + * \author Andrey Semashev + * \date 28.06.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_ + +#include <boost/parameter/keyword.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/facilities/intercept.hpp> +#include <boost/preprocessor/arithmetic/dec.hpp> +#include <boost/preprocessor/tuple/elem.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_MAX_PARAMETER_ARGS +//! The maximum number of named arguments that are accepted by constructors and functions +#define BOOST_LOG_MAX_PARAMETER_ARGS 16 +#endif + +// The macro applies the passed macro with the specified arguments BOOST_LOG_MAX_PARAMETER_ARGS times +#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(macro, args)\ + public:\ + BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, macro, args) + + +#define BOOST_LOG_CTOR_FORWARD(z, n, types)\ + template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ + explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\ + BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))) {} + +// The macro expands to a number of templated constructors that aggregate their named arguments +// into an ArgumentsPack and pass it to the base class constructor. +#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_FORWARD(class_type, base_type)\ + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_CTOR_FORWARD, (class_type, base_type)) + + +#define BOOST_LOG_CTOR_CALL(z, n, types)\ + template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ + explicit BOOST_PP_TUPLE_ELEM(2, 0, types)(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg))\ + { BOOST_PP_TUPLE_ELEM(2, 1, types)((BOOST_PP_ENUM_PARAMS(n, arg))); } + +// The macro expands to a number of templated constructors that aggregate their named arguments +// into an ArgumentsPack and pass it to a function call. +#define BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_CALL(class_type, fun)\ + BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_CTOR_CALL, (class_type, fun)) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +// Yeah, not too cute. The empty_arg_list class should really be public. +typedef boost::parameter::aux::empty_arg_list empty_arg_list; + +#if !(defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_LOG_NO_CXX11_ARG_PACKS_TO_NON_VARIADIC_ARGS_EXPANSION)) + +//! The metafunction generates argument pack +template< typename ArgT0, typename... ArgsT > +struct make_arg_list +{ + typedef boost::parameter::aux::arg_list< ArgT0, typename make_arg_list< ArgsT... >::type > type; +}; + +template< typename ArgT0 > +struct make_arg_list< ArgT0 > +{ + typedef boost::parameter::aux::arg_list< ArgT0 > type; +}; + +#else + +//! The metafunction generates argument pack +template< typename ArgT0, BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PARAMETER_ARGS), typename T, = void BOOST_PP_INTERCEPT) > +struct make_arg_list +{ + typedef boost::parameter::aux::arg_list< ArgT0, typename make_arg_list< BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PARAMETER_ARGS), T) >::type > type; +}; + +template< typename ArgT0 > +struct make_arg_list< ArgT0, BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(BOOST_LOG_MAX_PARAMETER_ARGS), void BOOST_PP_INTERCEPT) > +{ + typedef boost::parameter::aux::arg_list< ArgT0 > type; +}; + +#endif + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_PARAMETER_TOOLS_HPP_INCLUDED_ diff --git a/boost/log/detail/pp_identity.hpp b/boost/log/detail/pp_identity.hpp new file mode 100644 index 0000000000..8daaf951b8 --- /dev/null +++ b/boost/log/detail/pp_identity.hpp @@ -0,0 +1,27 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 pp_identity.hpp + * \author Andrey Semashev + * \date 12.02.2011 + * + * This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_LOG_PP_IDENTITY(z, n, data) data + +#endif // BOOST_LOG_DETAIL_PP_IDENTITY_HPP_INCLUDED_ diff --git a/boost/log/detail/process_id.hpp b/boost/log/detail/process_id.hpp new file mode 100644 index 0000000000..3532506c2a --- /dev/null +++ b/boost/log/detail/process_id.hpp @@ -0,0 +1,60 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 process_id.hpp + * \author Andrey Semashev + * \date 12.09.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_PROCESS_ID_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_PROCESS_ID_HPP_INCLUDED_ + +#include <iosfwd> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/id.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The process id descriptor +struct process +{ + typedef unsigned long native_type; + typedef boost::log::aux::id< process > id; +}; + +namespace this_process { + +//! The function returns current process identifier +BOOST_LOG_API process::id get_id(); + +} // namespace this_process + +template< typename CharT, typename TraitsT > +BOOST_LOG_API std::basic_ostream< CharT, TraitsT >& +operator<< (std::basic_ostream< CharT, TraitsT >& strm, process::id const& pid); + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_PROCESS_ID_HPP_INCLUDED_ diff --git a/boost/log/detail/setup_config.hpp b/boost/log/detail/setup_config.hpp new file mode 100644 index 0000000000..11239592af --- /dev/null +++ b/boost/log/detail/setup_config.hpp @@ -0,0 +1,61 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 setup_config.hpp + * \author Andrey Semashev + * \date 14.09.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB) + +// Detect if we're dealing with dll +# if defined(BOOST_LOG_SETUP_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) +# define BOOST_LOG_SETUP_DLL +# endif + +# if defined(BOOST_HAS_DECLSPEC) && defined(BOOST_LOG_SETUP_DLL) +# define BOOST_LOG_SETUP_API __declspec(dllimport) +# else +# define BOOST_LOG_SETUP_API +# endif // defined(BOOST_HAS_DECLSPEC) +// +// Automatically link to the correct build variant where possible. +// +# if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_LOG_SETUP_NO_LIB) +# define BOOST_LIB_NAME boost_log_setup +# if defined(BOOST_LOG_SETUP_DLL) +# define BOOST_DYN_LINK +# endif +# include <boost/config/auto_link.hpp> +# endif // auto-linking disabled + +#else // !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB) + +# if defined(BOOST_HAS_DECLSPEC) && defined(BOOST_LOG_SETUP_DLL) +# define BOOST_LOG_SETUP_API __declspec(dllexport) +# elif defined(__GNUC__) && __GNUC__ >= 4 && (defined(linux) || defined(__linux) || defined(__linux__)) +# define BOOST_LOG_SETUP_API __attribute__((visibility("default"))) +# else +# define BOOST_LOG_SETUP_API +# endif + +#endif // !defined(BOOST_LOG_SETUP_BUILDING_THE_LIB) + +#endif // BOOST_LOG_DETAIL_SETUP_CONFIG_HPP_INCLUDED_ diff --git a/boost/log/detail/singleton.hpp b/boost/log/detail/singleton.hpp new file mode 100644 index 0000000000..ac1ac1afe0 --- /dev/null +++ b/boost/log/detail/singleton.hpp @@ -0,0 +1,89 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 singleton.hpp + * \author Andrey Semashev + * \date 20.04.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_SINGLETON_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SINGLETON_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/utility/once_block.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A base class for singletons, constructed on-demand +template< typename DerivedT, typename StorageT = DerivedT > +class lazy_singleton +{ +public: + BOOST_DEFAULTED_FUNCTION(lazy_singleton(), {}) + + //! Returns the singleton instance + static StorageT& get() + { + BOOST_LOG_ONCE_BLOCK() + { + DerivedT::init_instance(); + } + return get_instance(); + } + + //! Initializes the singleton instance + static void init_instance() + { + get_instance(); + } + + BOOST_DELETED_FUNCTION(lazy_singleton(lazy_singleton const&)) + BOOST_DELETED_FUNCTION(lazy_singleton& operator= (lazy_singleton const&)) + +protected: + //! Returns the singleton instance (not thread-safe) + static StorageT& get_instance() + { + static StorageT instance; + return instance; + } +}; + +//! A base class for singletons, constructed on namespace scope initialization stage +template< typename DerivedT, typename StorageT = DerivedT > +class singleton : + public lazy_singleton< DerivedT, StorageT > +{ +public: + static StorageT& instance; +}; + +template< typename DerivedT, typename StorageT > +StorageT& singleton< DerivedT, StorageT >::instance = + lazy_singleton< DerivedT, StorageT >::get(); + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_SINGLETON_HPP_INCLUDED_ diff --git a/boost/log/detail/sink_init_helpers.hpp b/boost/log/detail/sink_init_helpers.hpp new file mode 100644 index 0000000000..060aab7fc8 --- /dev/null +++ b/boost/log/detail/sink_init_helpers.hpp @@ -0,0 +1,118 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 sink_init_helpers.hpp + * \author Andrey Semashev + * \date 14.03.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_SINK_INIT_HELPERS_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SINK_INIT_HELPERS_HPP_INCLUDED_ + +#include <string> +#include <boost/mpl/bool.hpp> +#include <boost/parameter/binding.hpp> +#include <boost/type_traits/is_void.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/phoenix/core/is_actor.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/core/core.hpp> +#include <boost/log/expressions/filter.hpp> +#include <boost/log/expressions/formatter.hpp> +#include <boost/log/utility/setup/filter_parser.hpp> +#include <boost/log/utility/setup/formatter_parser.hpp> +#include <boost/log/keywords/filter.hpp> +#include <boost/log/keywords/format.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +// The function creates a filter functional object from the provided argument +template< typename CharT > +inline filter acquire_filter(const CharT* filter) +{ + return boost::log::parse_filter(filter); +} +template< typename CharT, typename TraitsT, typename AllocatorT > +inline filter acquire_filter(std::basic_string< CharT, TraitsT, AllocatorT > const& filter) +{ + return boost::log::parse_filter(filter); +} +template< typename FilterT > +inline typename enable_if< + phoenix::is_actor< FilterT >, + FilterT const& +>::type acquire_filter(FilterT const& filter) +{ + return filter; +} + +// The function installs filter into the sink, if provided in the arguments pack +template< typename SinkT, typename ArgsT > +inline void setup_filter(SinkT&, ArgsT const&, mpl::true_) +{ +} + +template< typename SinkT, typename ArgsT > +inline void setup_filter(SinkT& s, ArgsT const& args, mpl::false_) +{ + s.set_filter(aux::acquire_filter(args[keywords::filter])); +} + + +// The function creates a filter functional object from the provided argument +template< typename CharT > +inline basic_formatter< CharT > acquire_formatter(const CharT* formatter) +{ + return boost::log::parse_formatter(formatter); +} +template< typename CharT, typename TraitsT, typename AllocatorT > +inline basic_formatter< CharT > acquire_formatter(std::basic_string< CharT, TraitsT, AllocatorT > const& formatter) +{ + return boost::log::parse_formatter(formatter); +} +template< typename FormatterT > +inline typename enable_if< + phoenix::is_actor< FormatterT >, + FormatterT const& +>::type acquire_formatter(FormatterT const& formatter) +{ + return formatter; +} + +// The function installs filter into the sink, if provided in the arguments pack +template< typename SinkT, typename ArgsT > +inline void setup_formatter(SinkT&, ArgsT const&, mpl::true_) +{ +} + +template< typename SinkT, typename ArgsT > +inline void setup_formatter(SinkT& s, ArgsT const& args, mpl::false_) +{ + s.set_formatter(aux::acquire_formatter(args[keywords::format])); +} + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_SINK_INIT_HELPERS_HPP_INCLUDED_ diff --git a/boost/log/detail/snprintf.hpp b/boost/log/detail/snprintf.hpp new file mode 100644 index 0000000000..ced0cd593a --- /dev/null +++ b/boost/log/detail/snprintf.hpp @@ -0,0 +1,106 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 snprintf.hpp + * \author Andrey Semashev + * \date 20.02.2009 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_ + +#include <stdio.h> +#include <cstddef> +#include <cstdarg> +#include <boost/log/detail/config.hpp> +#ifdef BOOST_LOG_USE_WCHAR_T +#include <wchar.h> +#endif // BOOST_LOG_USE_WCHAR_T +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +#if !defined(_MSC_VER) + +// Standard-conforming compilers already have the correct snprintfs +using ::snprintf; +using ::vsnprintf; + +# ifdef BOOST_LOG_USE_WCHAR_T +using ::swprintf; +using ::vswprintf; +# endif // BOOST_LOG_USE_WCHAR_T + +#else // !defined(_MSC_VER) + +// MSVC snprintfs are not conforming but they are good enough for our cases +inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args) +{ + int n = _vsnprintf(buf, size, format, args); + if (static_cast< unsigned int >(n) >= size) + { + n = static_cast< int >(size); + buf[size - 1] = '\0'; + } + return n; +} + +# ifdef BOOST_LOG_USE_WCHAR_T +inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args) +{ + int n = _vsnwprintf(buf, size, format, args); + if (static_cast< unsigned int >(n) >= size) + { + n = static_cast< int >(size); + buf[size - 1] = L'\0'; + } + return n; +} +# endif // BOOST_LOG_USE_WCHAR_T + +inline int snprintf(char* buf, std::size_t size, const char* format, ...) +{ + std::va_list args; + va_start(args, format); + int n = vsnprintf(buf, size, format, args); + va_end(args); + return n; +} + +# ifdef BOOST_LOG_USE_WCHAR_T +inline int swprintf(wchar_t* buf, std::size_t size, const wchar_t* format, ...) +{ + std::va_list args; + va_start(args, format); + int n = vswprintf(buf, size, format, args); + va_end(args); + return n; +} +# endif // BOOST_LOG_USE_WCHAR_T + +#endif // !defined(_MSC_VER) + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_SNPRINTF_HPP_INCLUDED_ diff --git a/boost/log/detail/spin_mutex.hpp b/boost/log/detail/spin_mutex.hpp new file mode 100644 index 0000000000..727d6d1ade --- /dev/null +++ b/boost/log/detail/spin_mutex.hpp @@ -0,0 +1,319 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 spin_mutex.hpp + * \author Andrey Semashev + * \date 01.08.2010 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_SPIN_MUTEX_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_SPIN_MUTEX_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_NO_THREADS + +#include <boost/throw_exception.hpp> +#include <boost/thread/exceptions.hpp> + +#if defined(BOOST_THREAD_POSIX) // This one can be defined by users, so it should go first +#define BOOST_LOG_SPIN_MUTEX_USE_PTHREAD +#elif defined(BOOST_WINDOWS) +#define BOOST_LOG_SPIN_MUTEX_USE_WINAPI +#elif defined(BOOST_HAS_PTHREADS) +#define BOOST_LOG_SPIN_MUTEX_USE_PTHREAD +#endif + +#if defined(BOOST_LOG_SPIN_MUTEX_USE_WINAPI) + +#include <boost/detail/interlocked.hpp> + +#if defined(BOOST_USE_WINDOWS_H) + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#include <windows.h> + +#else // defined(BOOST_USE_WINDOWS_H) + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +extern "C" { + +__declspec(dllimport) int __stdcall SwitchToThread(); + +} // extern "C" + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_USE_WINDOWS_H + +#if defined(__INTEL_COMPILER) || defined(_MSC_VER) +# if defined(_M_IX86) +# define BOOST_LOG_PAUSE_OP __asm { pause } +# elif defined(_M_AMD64) +extern "C" void _mm_pause(void); +#pragma intrinsic(_mm_pause) +# define BOOST_LOG_PAUSE_OP _mm_pause() +# endif +# if defined(__INTEL_COMPILER) +# define BOOST_LOG_COMPILER_BARRIER __memory_barrier() +# else +extern "C" void _ReadWriteBarrier(void); +#pragma intrinsic(_ReadWriteBarrier) +# define BOOST_LOG_COMPILER_BARRIER _ReadWriteBarrier() +# endif +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +# define BOOST_LOG_PAUSE_OP __asm__ __volatile__("pause;") +# define BOOST_LOG_COMPILER_BARRIER __asm__ __volatile__("" : : : "memory") +#endif + +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A simple spinning mutex +class spin_mutex +{ +private: + enum state + { + initial_pause = 2, + max_pause = 16 + }; + + long m_State; + +public: + spin_mutex() : m_State(0) {} + + bool try_lock() + { + return (BOOST_INTERLOCKED_COMPARE_EXCHANGE(&m_State, 1L, 0L) == 0L); + } + + void lock() + { +#if defined(BOOST_LOG_PAUSE_OP) + unsigned int pause_count = initial_pause; +#endif + while (!try_lock()) + { +#if defined(BOOST_LOG_PAUSE_OP) + if (pause_count < max_pause) + { + for (unsigned int i = 0; i < pause_count; ++i) + { + BOOST_LOG_PAUSE_OP; + } + pause_count += pause_count; + } + else + { + // Restart spinning after waking up this thread + pause_count = initial_pause; + SwitchToThread(); + } +#else + SwitchToThread(); +#endif + } + } + + void unlock() + { +#if (defined(_M_IX86) || defined(_M_AMD64)) && defined(BOOST_LOG_COMPILER_BARRIER) + BOOST_LOG_COMPILER_BARRIER; + m_State = 0L; + BOOST_LOG_COMPILER_BARRIER; +#else + BOOST_INTERLOCKED_EXCHANGE(&m_State, 0L); +#endif + } + + // Non-copyable + BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&)) + BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&)) +}; + +#undef BOOST_LOG_PAUSE_OP +#undef BOOST_LOG_COMPILER_BARRIER + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#elif defined(BOOST_LOG_SPIN_MUTEX_USE_PTHREAD) + +#include <pthread.h> +#include <boost/assert.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +#if defined(_POSIX_SPIN_LOCKS) && _POSIX_SPIN_LOCKS > 0 + +//! A simple spinning mutex +class spin_mutex +{ +private: + pthread_spinlock_t m_State; + +public: + spin_mutex() + { + const int err = pthread_spin_init(&m_State, PTHREAD_PROCESS_PRIVATE); + if (err != 0) + throw_exception< thread_resource_error >(err, "failed to initialize a spin mutex", "spin_mutex::spin_mutex()", __FILE__, __LINE__); + } + + ~spin_mutex() + { + BOOST_VERIFY(pthread_spin_destroy(&m_State) == 0); + } + + bool try_lock() + { + const int err = pthread_spin_trylock(&m_State); + if (err == 0) + return true; + if (err != EBUSY) + throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::try_lock()", __FILE__, __LINE__); + return false; + } + + void lock() + { + const int err = pthread_spin_lock(&m_State); + if (err != 0) + throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::lock()", __FILE__, __LINE__); + } + + void unlock() + { + BOOST_VERIFY(pthread_spin_unlock(&m_State) == 0); + } + + // Non-copyable + BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&)) + BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&)) + +private: + template< typename ExceptionT > + static BOOST_NOINLINE BOOST_LOG_NORETURN void throw_exception(int err, const char* descr, const char* func, const char* file, int line) + { +#if !defined(BOOST_EXCEPTION_DISABLE) + boost::exception_detail::throw_exception_(ExceptionT(err, descr), func, file, line); +#else + boost::throw_exception(ExceptionT(err, descr)); +#endif + } +}; + +#else // defined(_POSIX_SPIN_LOCKS) + +//! Backup implementation in case if pthreads don't support spin locks +class spin_mutex +{ +private: + pthread_mutex_t m_State; + +public: + spin_mutex() + { + const int err = pthread_mutex_init(&m_State, NULL); + if (err != 0) + throw_exception< thread_resource_error >(err, "failed to initialize a spin mutex", "spin_mutex::spin_mutex()", __FILE__, __LINE__); + } + + ~spin_mutex() + { + BOOST_VERIFY(pthread_mutex_destroy(&m_State) == 0); + } + + bool try_lock() + { + const int err = pthread_mutex_trylock(&m_State); + if (err == 0) + return true; + if (err != EBUSY) + throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::try_lock()", __FILE__, __LINE__); + return false; + } + + void lock() + { + const int err = pthread_mutex_lock(&m_State); + if (err != 0) + throw_exception< lock_error >(err, "failed to lock a spin mutex", "spin_mutex::lock()", __FILE__, __LINE__); + } + + void unlock() + { + BOOST_VERIFY(pthread_mutex_unlock(&m_State) == 0); + } + + // Non-copyable + BOOST_DELETED_FUNCTION(spin_mutex(spin_mutex const&)) + BOOST_DELETED_FUNCTION(spin_mutex& operator= (spin_mutex const&)) + +private: + template< typename ExceptionT > + static BOOST_NOINLINE BOOST_LOG_NORETURN void throw_exception(int err, const char* descr, const char* func, const char* file, int line) + { +#if !defined(BOOST_EXCEPTION_DISABLE) + boost::exception_detail::throw_exception_(ExceptionT(err, descr), func, file, line); +#else + boost::throw_exception(ExceptionT(err, descr)); +#endif + } +}; + +#endif // defined(_POSIX_SPIN_LOCKS) + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif + +#endif // BOOST_LOG_NO_THREADS + +#endif // BOOST_LOG_DETAIL_SPIN_MUTEX_HPP_INCLUDED_ diff --git a/boost/log/detail/tagged_integer.hpp b/boost/log/detail/tagged_integer.hpp new file mode 100644 index 0000000000..5aef5bbfcc --- /dev/null +++ b/boost/log/detail/tagged_integer.hpp @@ -0,0 +1,147 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 tagged_integer.hpp + * \author Andrey Semashev + * \date 11.01.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_TAGGED_INTEGER_HPP_INCLUDED_ +#define BOOST_LOG_TAGGED_INTEGER_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! A tagged integer wrapper for type safety +template< typename IntT, typename TagT > +struct tagged_integer +{ + //! Contained value type + typedef IntT integer_type; + //! Tag + typedef TagT tag; + + //! Contained value + integer_type value; + + //! Conversion operator + operator integer_type() const { return value; } + + // Increment + tagged_integer& operator++ () { ++value; return *this; } + tagged_integer operator++ (int) { tagged_integer temp = *this; ++value; return temp; } + // Decrement + tagged_integer& operator-- () { --value; return *this; } + tagged_integer operator-- (int) { tagged_integer temp = *this; --value; return temp; } + +#define BOOST_LOG_TAGGED_INTEGER_OP(op)\ + tagged_integer& operator op (tagged_integer const& that) { value op that.value; return *this; } + + BOOST_LOG_TAGGED_INTEGER_OP(|=) + BOOST_LOG_TAGGED_INTEGER_OP(&=) + BOOST_LOG_TAGGED_INTEGER_OP(^=) + BOOST_LOG_TAGGED_INTEGER_OP(+=) + BOOST_LOG_TAGGED_INTEGER_OP(-=) + BOOST_LOG_TAGGED_INTEGER_OP(*=) + BOOST_LOG_TAGGED_INTEGER_OP(/=) + BOOST_LOG_TAGGED_INTEGER_OP(%=) + +#undef BOOST_LOG_TAGGED_INTEGER_OP + + //! Inversion operator + tagged_integer& operator~ () { ~value; return *this; } + + // Shift operators + template< typename T > + tagged_integer& operator<<= (T const& that) { value <<= that; return *this; } + template< typename T > + tagged_integer& operator>>= (T const& that) { value >>= that; return *this; } + +private: + // Protection against improper usage + template< typename T1, typename T2 > + tagged_integer& operator<<= (tagged_integer< T1, T2 > const&); + template< typename T1, typename T2 > + tagged_integer& operator>>= (tagged_integer< T1, T2 > const&); +}; + + // Relational operators +#define BOOST_LOG_TAGGED_INTEGER_OP(op)\ + template< typename IntT, typename TagT >\ + inline bool operator op (\ + tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right)\ + {\ + return (left.value op right.value);\ + } + +BOOST_LOG_TAGGED_INTEGER_OP(==) +BOOST_LOG_TAGGED_INTEGER_OP(!=) +BOOST_LOG_TAGGED_INTEGER_OP(<) +BOOST_LOG_TAGGED_INTEGER_OP(>) +BOOST_LOG_TAGGED_INTEGER_OP(<=) +BOOST_LOG_TAGGED_INTEGER_OP(>=) + +#undef BOOST_LOG_TAGGED_INTEGER_OP + +#define BOOST_LOG_TAGGED_INTEGER_OP(op)\ + template< typename IntT, typename TagT >\ + inline tagged_integer< IntT, TagT > operator op (\ + tagged_integer< IntT, TagT > const& left, tagged_integer< IntT, TagT > const& right)\ + {\ + tagged_integer< IntT, TagT > temp = left;\ + temp op##= right;\ + return temp;\ + } + +BOOST_LOG_TAGGED_INTEGER_OP(|) +BOOST_LOG_TAGGED_INTEGER_OP(&) +BOOST_LOG_TAGGED_INTEGER_OP(^) +BOOST_LOG_TAGGED_INTEGER_OP(+) +BOOST_LOG_TAGGED_INTEGER_OP(-) +BOOST_LOG_TAGGED_INTEGER_OP(*) +BOOST_LOG_TAGGED_INTEGER_OP(/) +BOOST_LOG_TAGGED_INTEGER_OP(%) + +#undef BOOST_LOG_TAGGED_INTEGER_OP + +#define BOOST_LOG_TAGGED_INTEGER_OP(op)\ + template< typename IntT, typename TagT, typename T >\ + inline tagged_integer< IntT, TagT > operator op (\ + tagged_integer< IntT, TagT > const& left, T const& right)\ + {\ + tagged_integer< IntT, TagT > temp = left;\ + temp op##= right;\ + return temp;\ + } + +BOOST_LOG_TAGGED_INTEGER_OP(<<) +BOOST_LOG_TAGGED_INTEGER_OP(>>) + +#undef BOOST_LOG_TAGGED_INTEGER_OP + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_TAGGED_INTEGER_HPP_INCLUDED_ diff --git a/boost/log/detail/thread_id.hpp b/boost/log/detail/thread_id.hpp new file mode 100644 index 0000000000..3b592c2c25 --- /dev/null +++ b/boost/log/detail/thread_id.hpp @@ -0,0 +1,65 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 thread_id.hpp + * \author Andrey Semashev + * \date 08.01.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_THREAD_ID_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_THREAD_ID_HPP_INCLUDED_ + +#include <iosfwd> +#include <boost/cstdint.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/id.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The thread id descriptor +struct thread +{ +#if defined(BOOST_WINDOWS) + typedef uint32_t native_type; +#else + typedef uintmax_t native_type; +#endif + typedef boost::log::aux::id< thread > id; +}; + +namespace this_thread { + +//! The function returns current thread identifier +BOOST_LOG_API thread::id const& get_id(); + +} // namespace this_thread + +template< typename CharT, typename TraitsT > +BOOST_LOG_API std::basic_ostream< CharT, TraitsT >& +operator<< (std::basic_ostream< CharT, TraitsT >& strm, thread::id const& tid); + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_THREAD_ID_HPP_INCLUDED_ diff --git a/boost/log/detail/thread_specific.hpp b/boost/log/detail/thread_specific.hpp new file mode 100644 index 0000000000..72d2a3b22e --- /dev/null +++ b/boost/log/detail/thread_specific.hpp @@ -0,0 +1,116 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 thread_specific.hpp + * \author Andrey Semashev + * \date 01.03.2008 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_ + +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_pod.hpp> +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_LOG_NO_THREADS) + +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Base class for TLS to hide platform-specific storage management +class thread_specific_base +{ +private: + union key_storage + { + void* as_pointer; + unsigned int as_dword; + }; + + key_storage m_Key; + +protected: + BOOST_LOG_API thread_specific_base(); + BOOST_LOG_API ~thread_specific_base(); + BOOST_LOG_API void* get_content() const; + BOOST_LOG_API void set_content(void* value) const; + + // Copying prohibited + BOOST_DELETED_FUNCTION(thread_specific_base(thread_specific_base const&)) + BOOST_DELETED_FUNCTION(thread_specific_base& operator= (thread_specific_base const&)) +}; + +//! A TLS wrapper for small POD types with least possible overhead +template< typename T > +class thread_specific : + public thread_specific_base +{ + BOOST_STATIC_ASSERT_MSG(sizeof(T) <= sizeof(void*) && is_pod< T >::value, "Boost.Log: Thread-specific values must be PODs and must not exceed the size of a pointer"); + + //! Union to perform type casting + union value_storage + { + void* as_pointer; + T as_value; + }; + +public: + //! Default constructor + BOOST_DEFAULTED_FUNCTION(thread_specific(), {}) + //! Initializing constructor + thread_specific(T const& value) + { + set(value); + } + //! Assignment + thread_specific& operator= (T const& value) + { + set(value); + return *this; + } + + //! Accessor + T get() const + { + value_storage cast = {}; + cast.as_pointer = thread_specific_base::get_content(); + return cast.as_value; + } + + //! Setter + void set(T const& value) + { + value_storage cast = {}; + cast.as_value = value; + thread_specific_base::set_content(cast.as_pointer); + } +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // !defined(BOOST_LOG_NO_THREADS) + +#endif // BOOST_LOG_DETAIL_THREAD_SPECIFIC_HPP_INCLUDED_ diff --git a/boost/log/detail/threadsafe_queue.hpp b/boost/log/detail/threadsafe_queue.hpp new file mode 100644 index 0000000000..a1e78249f0 --- /dev/null +++ b/boost/log/detail/threadsafe_queue.hpp @@ -0,0 +1,277 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 threadsafe_queue.hpp + * \author Andrey Semashev + * \date 05.11.2010 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_THREADSAFE_QUEUE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_THREADSAFE_QUEUE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_LOG_NO_THREADS + +#include <new> +#include <memory> +#include <cstddef> +#include <boost/aligned_storage.hpp> +#include <boost/move/core.hpp> +#include <boost/move/utility.hpp> +#include <boost/type_traits/alignment_of.hpp> +#include <boost/type_traits/type_with_alignment.hpp> +#include <boost/log/detail/header.hpp> + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Base class for the thread-safe queue implementation +struct threadsafe_queue_impl +{ + struct +#if defined(__GNUC__) + // Explicitly mark the type so that it may alias other types + __attribute__ ((__may_alias__)) +#endif + pointer_storage + { + union + { + void* data[2]; + type_with_alignment< 2 * sizeof(void*) >::type alignment; + }; + }; + + struct node_base + { + pointer_storage next; + }; + + static BOOST_LOG_API threadsafe_queue_impl* create(node_base* first_node); + + static BOOST_LOG_API void* operator new (std::size_t size); + static BOOST_LOG_API void operator delete (void* p, std::size_t); + + virtual ~threadsafe_queue_impl() {} + virtual node_base* reset_last_node() = 0; + virtual bool unsafe_empty() = 0; + virtual void push(node_base* p) = 0; + virtual bool try_pop(node_base*& node_to_free, node_base*& node_with_value) = 0; +}; + +//! A helper class to compose some of the types used by the queue +template< typename T, typename AllocatorT > +struct threadsafe_queue_types +{ + struct node : + public threadsafe_queue_impl::node_base + { + typedef typename aligned_storage< sizeof(T), alignment_of< T >::value >::type storage_type; + storage_type storage; + + node() {} + explicit node(T const& val) { new (storage.address()) T(val); } + T& value() { return *static_cast< T* >(storage.address()); } + void destroy() { static_cast< T* >(storage.address())->~T(); } + }; + + typedef typename AllocatorT::BOOST_NESTED_TEMPLATE rebind< node >::other allocator_type; +}; + +/*! + * \brief An unbounded thread-safe queue + * + * The implementation is based on algorithms published in the "Simple, Fast, + * and Practical Non-Blocking and Blocking Concurrent Queue Algorithms" article + * in PODC96 by Maged M. Michael and Michael L. Scott. Pseudocode is available here: + * http://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html + * + * The implementation provides thread-safe \c push and \c try_pop operations, as well as + * a thread-unsafe \c empty operation. The queue imposes the following requirements + * on the element type: + * + * \li Default constructible, the default constructor must not throw. + * \li Copy constructible. + * \li Movable (i.e. there should be an efficient move assignment for this type). + * + * The last requirement is not mandatory but is crucial for decent performance. + */ +template< typename T, typename AllocatorT = std::allocator< void > > +class threadsafe_queue : + private threadsafe_queue_types< T, AllocatorT >::allocator_type +{ +private: + typedef typename threadsafe_queue_types< T, AllocatorT >::allocator_type base_type; + typedef typename threadsafe_queue_types< T, AllocatorT >::node node; + + //! A simple scope guard to automate memory reclaiming + struct auto_deallocate; + friend struct auto_deallocate; + struct auto_deallocate + { + auto_deallocate(base_type* alloc, node* dealloc, node* destr) : + m_pAllocator(alloc), + m_pDeallocate(dealloc), + m_pDestroy(destr) + { + } + ~auto_deallocate() + { + m_pAllocator->deallocate(m_pDeallocate, 1); + m_pDestroy->destroy(); + } + + private: + base_type* m_pAllocator; + node* m_pDeallocate; + node* m_pDestroy; + }; + +public: + typedef T value_type; + typedef T& reference; + typedef T const& const_reference; + typedef T* pointer; + typedef T const* const_pointer; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef AllocatorT allocator_type; + +public: + /*! + * Default constructor, creates an empty queue. Unlike most containers, + * the constructor requires memory allocation. + * + * \throw std::bad_alloc if there is not sufficient memory + */ + threadsafe_queue(base_type const& alloc = base_type()) : + base_type(alloc) + { + node* p = base_type::allocate(1); + if (p) + { + try + { + new (p) node(); + try + { + m_pImpl = threadsafe_queue_impl::create(p); + } + catch (...) + { + p->~node(); + throw; + } + } + catch (...) + { + base_type::deallocate(p, 1); + throw; + } + } + else + throw std::bad_alloc(); + } + /*! + * Destructor + */ + ~threadsafe_queue() + { + // Clear the queue + if (!unsafe_empty()) + { + value_type value; + while (try_pop(value)); + } + + // Remove the last dummy node + node* p = static_cast< node* >(m_pImpl->reset_last_node()); + p->~node(); + base_type::deallocate(p, 1); + + delete m_pImpl; + } + + /*! + * Checks if the queue is empty. Not thread-safe, the returned result may not be actual. + */ + bool unsafe_empty() const { return m_pImpl->unsafe_empty(); } + + /*! + * Puts a new element to the end of the queue. Thread-safe, can be called + * concurrently by several threads, and concurrently with the \c pop operation. + */ + void push(const_reference value) + { + node* p = base_type::allocate(1); + if (p) + { + try + { + new (p) node(value); + } + catch (...) + { + base_type::deallocate(p, 1); + throw; + } + m_pImpl->push(p); + } + else + throw std::bad_alloc(); + } + + /*! + * Attempts to pop an element from the beginning of the queue. Thread-safe, can + * be called concurrently with the \c push operation. Should not be called by + * several threads concurrently. + */ + bool try_pop(reference value) + { + threadsafe_queue_impl::node_base *dealloc, *destr; + if (m_pImpl->try_pop(dealloc, destr)) + { + node* p = static_cast< node* >(destr); + auto_deallocate guard(static_cast< base_type* >(this), static_cast< node* >(dealloc), p); + value = boost::move(p->value()); + return true; + } + else + return false; + } + + // Copying and assignment is prohibited + BOOST_DELETED_FUNCTION(threadsafe_queue(threadsafe_queue const&)) + BOOST_DELETED_FUNCTION(threadsafe_queue& operator= (threadsafe_queue const&)) + +private: + //! Pointer to the implementation + threadsafe_queue_impl* m_pImpl; +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_NO_THREADS + +#endif // BOOST_LOG_DETAIL_THREADSAFE_QUEUE_HPP_INCLUDED_ diff --git a/boost/log/detail/timestamp.hpp b/boost/log/detail/timestamp.hpp new file mode 100644 index 0000000000..719061fb01 --- /dev/null +++ b/boost/log/detail/timestamp.hpp @@ -0,0 +1,99 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 timestamp.hpp + * \author Andrey Semashev + * \date 31.07.2011 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_TIMESTAMP_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_TIMESTAMP_HPP_INCLUDED_ + +#include <boost/cstdint.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +/*! + * Duration between two timestamps + */ +class duration +{ + int64_t m_ticks; + +public: + explicit duration(int64_t ticks = 0) : m_ticks(ticks) {} + +#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + int64_t milliseconds() const { return m_ticks; } +#else + BOOST_LOG_API int64_t milliseconds() const; +#endif +}; + +/*! + * Opaque timestamp class + */ +class timestamp +{ + uint64_t m_ticks; + +public: + explicit timestamp(uint64_t ticks = 0) : m_ticks(ticks) {} + + duration operator- (timestamp that) const + { + return duration(m_ticks - that.m_ticks); + } +}; + +/*! + * \fn get_timestamp + * + * The function returns a timestamp, in opaque units since an unspecified + * time point. This timer is guaranteed to be monotonic, it should not + * be affected by clock changes, either manual or seasonal. Also, it + * should be as fast as possible. + */ +#if defined(BOOST_WINDOWS) && !defined(__CYGWIN__) + +typedef uint64_t (__stdcall* get_tick_count_t)(); +extern BOOST_LOG_API get_tick_count_t get_tick_count; + +inline timestamp get_timestamp() +{ + return timestamp(get_tick_count()); +} + +#else + +typedef timestamp (*get_timestamp_t)(); +extern BOOST_LOG_API get_timestamp_t get_timestamp; + +#endif + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_TIMESTAMP_HPP_INCLUDED_ diff --git a/boost/log/detail/trivial_keyword.hpp b/boost/log/detail/trivial_keyword.hpp new file mode 100644 index 0000000000..d0e4f60713 --- /dev/null +++ b/boost/log/detail/trivial_keyword.hpp @@ -0,0 +1,43 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 trivial_keyword.hpp + * \author Andrey Semashev + * \date 02.12.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_TRIVIAL_KEYWORD_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_TRIVIAL_KEYWORD_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace trivial { + +//! Trivial severity keyword +BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", severity_level) + +} // namespace trivial + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_TRIVIAL_KEYWORD_HPP_INCLUDED_ diff --git a/boost/log/detail/unary_function_terminal.hpp b/boost/log/detail/unary_function_terminal.hpp new file mode 100644 index 0000000000..f9a3412acf --- /dev/null +++ b/boost/log/detail/unary_function_terminal.hpp @@ -0,0 +1,142 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 unary_function_terminal.hpp + * \author Andrey Semashev + * \date 21.07.2012 + * + * The header contains attribute value extractor adapter for constructing expression template terminals. + */ + +#ifndef BOOST_LOG_DETAIL_UNARY_FUNCTION_TERMINAL_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_UNARY_FUNCTION_TERMINAL_HPP_INCLUDED_ + +#include <boost/mpl/bool.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/fusion/sequence/intrinsic/at_c.hpp> +#include <boost/phoenix/core/is_nullary.hpp> +#include <boost/phoenix/core/environment.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/copy_cv.hpp> +#include <boost/log/detail/custom_terminal_spec.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace expressions { + +namespace aux { + +/*! + * \brief An adapter for a unary function to be used as a terminal in a Boost.Phoenix expression + * + * This class is an adapter between Boost.Phoenix expression invocation protocol and + * a unary function. It forwards the call to the base function, passing only the first argument + * from the original call. This allows to embed value extractors in template expressions. + */ +template< typename FunT > +class unary_function_terminal +{ +private: + //! Adopted function type + typedef FunT function_type; + //! Self type + typedef unary_function_terminal< function_type > this_type; + +public: + //! Internal typedef for type categorization + typedef void _is_boost_log_terminal; + + //! Function result type + template< typename > + struct result; + + template< typename ThisT, typename ContextT > + struct result< ThisT(ContextT) > + { + typedef typename remove_cv< + typename remove_reference< typename phoenix::result_of::env< ContextT >::type >::type + >::type env_type; + typedef typename env_type::args_type args_type; + typedef typename boost::log::aux::copy_cv< ThisT, function_type >::type cv_function_type; + + typedef typename boost::result_of< cv_function_type(typename fusion::result_of::at_c< args_type, 0 >::type) >::type type; + }; + +private: + //! Adopted function + function_type m_fun; + +public: + //! Default constructor + BOOST_DEFAULTED_FUNCTION(unary_function_terminal(), {}) + //! Copy constructor + unary_function_terminal(unary_function_terminal const& that) : m_fun(that.m_fun) {} + //! Initializing constructor + template< typename ArgT1 > + explicit unary_function_terminal(ArgT1 const& arg1) : m_fun(arg1) {} + //! Initializing constructor + template< typename ArgT1, typename ArgT2 > + unary_function_terminal(ArgT1 const& arg1, ArgT2 const& arg2) : m_fun(arg1, arg2) {} + //! Initializing constructor + template< typename ArgT1, typename ArgT2, typename ArgT3 > + unary_function_terminal(ArgT1 const& arg1, ArgT2 const& arg2, ArgT3 const& arg3) : m_fun(arg1, arg2, arg3) {} + + //! The operator forwards the call to the base function + template< typename ContextT > + typename result< this_type(ContextT const&) >::type + operator() (ContextT const& ctx) + { + return m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args())); + } + + //! The operator forwards the call to the base function + template< typename ContextT > + typename result< const this_type(ContextT const&) >::type + operator() (ContextT const& ctx) const + { + return m_fun(fusion::at_c< 0 >(phoenix::env(ctx).args())); + } +}; + +} // namespace aux + +} // namespace expressions + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +#ifndef BOOST_LOG_DOXYGEN_PASS + +namespace phoenix { + +namespace result_of { + +template< typename FunT > +struct is_nullary< custom_terminal< boost::log::expressions::aux::unary_function_terminal< FunT > > > : + public mpl::false_ +{ +}; + +} // namespace result_of + +} // namespace phoenix + +#endif // BOOST_LOG_DOXYGEN_PASS + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_UNARY_FUNCTION_TERMINAL_HPP_INCLUDED_ diff --git a/boost/log/detail/unhandled_exception_count.hpp b/boost/log/detail/unhandled_exception_count.hpp new file mode 100644 index 0000000000..17866c3b36 --- /dev/null +++ b/boost/log/detail/unhandled_exception_count.hpp @@ -0,0 +1,40 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 unhandled_exception_count.hpp + * \author Andrey Semashev + * \date 05.11.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_DETAIL_UNHANDLED_EXCEPTION_COUNT_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_UNHANDLED_EXCEPTION_COUNT_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Returns the number of currently pending exceptions +BOOST_LOG_API unsigned int unhandled_exception_count() BOOST_NOEXCEPT; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#endif // BOOST_LOG_DETAIL_UNHANDLED_EXCEPTION_COUNT_HPP_INCLUDED_ diff --git a/boost/log/detail/value_ref_visitation.hpp b/boost/log/detail/value_ref_visitation.hpp new file mode 100644 index 0000000000..795069d150 --- /dev/null +++ b/boost/log/detail/value_ref_visitation.hpp @@ -0,0 +1,107 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 value_ref_visitation.hpp + * \author Andrey Semashev + * \date 28.07.2012 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_VALUE_REF_VISITATION_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_VALUE_REF_VISITATION_HPP_INCLUDED_ + +#include <boost/mpl/at.hpp> +#include <boost/mpl/begin.hpp> +#include <boost/mpl/end.hpp> +#include <boost/mpl/advance.hpp> +#include <boost/mpl/erase.hpp> +#include <boost/mpl/size.hpp> +#include <boost/preprocessor/arithmetic/inc.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/preprocessor/iteration/iterate.hpp> +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifndef BOOST_LOG_VALUE_REF_VISITATION_UNROLL_COUNT +#define BOOST_LOG_VALUE_REF_VISITATION_UNROLL_COUNT 8 +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +template< typename SequenceT, typename VisitorT, unsigned int SizeV = mpl::size< SequenceT >::value > +struct apply_visitor_dispatch +{ + typedef typename VisitorT::result_type result_type; + + static BOOST_FORCEINLINE result_type call(const void* p, unsigned int type_index, VisitorT& visitor) + { + typedef typename mpl::begin< SequenceT >::type begin_type; + typedef typename mpl::advance_c< begin_type, SizeV / 2u >::type middle_type; + if (type_index < (SizeV / 2u)) + { + typedef typename mpl::erase< SequenceT, middle_type, typename mpl::end< SequenceT >::type >::type new_sequence; + typedef apply_visitor_dispatch< new_sequence, VisitorT > new_dispatch; + return new_dispatch::call(p, type_index, visitor); + } + else + { + typedef typename mpl::erase< SequenceT, begin_type, middle_type >::type new_sequence; + typedef apply_visitor_dispatch< new_sequence, VisitorT > new_dispatch; + return new_dispatch::call(p, type_index - (SizeV / 2u), visitor); + } + } +}; + +#define BOOST_LOG_AUX_CASE_ENTRY(z, i, data)\ + case i: return visitor(*static_cast< typename mpl::at_c< SequenceT, i >::type const* >(p)); + +#define BOOST_PP_FILENAME_1 <boost/log/detail/value_ref_visitation.hpp> +#define BOOST_PP_ITERATION_LIMITS (1, BOOST_PP_INC(BOOST_LOG_VALUE_REF_VISITATION_VTABLE_SIZE)) +#include BOOST_PP_ITERATE() + +#undef BOOST_LOG_AUX_CASE_ENTRY + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_VALUE_REF_VISITATION_HPP_INCLUDED_ + +#ifdef BOOST_PP_IS_ITERATING + +#define BOOST_LOG_AUX_SWITCH_SIZE BOOST_PP_ITERATION() + +template< typename SequenceT, typename VisitorT > +struct apply_visitor_dispatch< SequenceT, VisitorT, BOOST_LOG_AUX_SWITCH_SIZE > +{ + typedef typename VisitorT::result_type result_type; + + static BOOST_FORCEINLINE result_type call(const void* p, unsigned int type_index, VisitorT& visitor) + { + switch (type_index) + { + BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_AUX_SWITCH_SIZE, BOOST_LOG_AUX_CASE_ENTRY, ~) + default: + return visitor(*static_cast< typename mpl::at_c< SequenceT, 0 >::type const* >(p)); + } + } +}; + +#undef BOOST_LOG_AUX_SWITCH_SIZE + +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/log/detail/visible_type.hpp b/boost/log/detail/visible_type.hpp new file mode 100644 index 0000000000..2086278d42 --- /dev/null +++ b/boost/log/detail/visible_type.hpp @@ -0,0 +1,48 @@ +/* + * Copyright Andrey Semashev 2007 - 2014. + * 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 visible_type.hpp + * \author Andrey Semashev + * \date 08.03.2007 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. In this file + * internal configuration macros are defined. + */ + +#ifndef BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ +#define BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ + +#include <boost/log/detail/config.hpp> +#include <boost/log/detail/header.hpp> + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! The wrapper type whose type_info is always visible +template< typename T > +struct BOOST_SYMBOL_VISIBLE visible_type +{ + typedef T wrapped_type; +}; + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include <boost/log/detail/footer.hpp> + +#endif // BOOST_LOG_DETAIL_VISIBLE_TYPE_HPP_INCLUDED_ |