diff DEPENDENCIES/generic/include/boost/log/sinks/basic_sink_frontend.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DEPENDENCIES/generic/include/boost/log/sinks/basic_sink_frontend.hpp	Tue Aug 05 11:11:38 2014 +0100
@@ -0,0 +1,523 @@
+/*
+ *          Copyright Andrey Semashev 2007 - 2013.
+ * Distributed under the Boost Software License, Version 1.0.
+ *    (See accompanying file LICENSE_1_0.txt or copy at
+ *          http://www.boost.org/LICENSE_1_0.txt)
+ */
+/*!
+ * \file   basic_sink_frontend.hpp
+ * \author Andrey Semashev
+ * \date   14.07.2009
+ *
+ * The header contains implementation of a base class for sink frontends.
+ */
+
+#ifndef BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_
+#define BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_
+
+#include <boost/mpl/bool.hpp>
+#include <boost/log/detail/config.hpp>
+#include <boost/log/detail/cleanup_scope_guard.hpp>
+#include <boost/log/detail/code_conversion.hpp>
+#include <boost/log/detail/attachable_sstream_buf.hpp>
+#include <boost/log/detail/fake_mutex.hpp>
+#include <boost/log/core/record_view.hpp>
+#include <boost/log/sinks/sink.hpp>
+#include <boost/log/sinks/frontend_requirements.hpp>
+#include <boost/log/expressions/filter.hpp>
+#include <boost/log/expressions/formatter.hpp>
+#if !defined(BOOST_LOG_NO_THREADS)
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/tss.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/log/detail/locks.hpp>
+#include <boost/log/detail/light_rw_mutex.hpp>
+#include <boost/concept_check.hpp>
+#endif // !defined(BOOST_LOG_NO_THREADS)
+#include <boost/log/detail/header.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace boost {
+
+BOOST_LOG_OPEN_NAMESPACE
+
+namespace sinks {
+
+//! A base class for a logging sink frontend
+class BOOST_LOG_NO_VTABLE basic_sink_frontend :
+    public sink
+{
+    //! Base type
+    typedef sink base_type;
+
+public:
+    //! An exception handler type
+    typedef base_type::exception_handler_type exception_handler_type;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+protected:
+    //! Mutex type
+    typedef boost::log::aux::light_rw_mutex mutex_type;
+
+private:
+    //! Synchronization mutex
+    mutable mutex_type m_Mutex;
+#endif
+
+private:
+    //! Filter
+    filter m_Filter;
+    //! Exception handler
+    exception_handler_type m_ExceptionHandler;
+
+public:
+    /*!
+     * \brief Initializing constructor
+     *
+     * \param cross_thread The flag indicates whether the sink passes log records between different threads
+     */
+    explicit basic_sink_frontend(bool cross_thread) : sink(cross_thread)
+    {
+    }
+
+    /*!
+     * The method sets sink-specific filter functional object
+     */
+    template< typename FunT >
+    void set_filter(FunT const& filter)
+    {
+        BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);)
+        m_Filter = filter;
+    }
+    /*!
+     * The method resets the filter
+     */
+    void reset_filter()
+    {
+        BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);)
+        m_Filter.reset();
+    }
+
+    /*!
+     * The method sets an exception handler function
+     */
+    template< typename FunT >
+    void set_exception_handler(FunT const& handler)
+    {
+        BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);)
+        m_ExceptionHandler = handler;
+    }
+
+    /*!
+     * The method resets the exception handler function
+     */
+    void reset_exception_handler()
+    {
+        BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< mutex_type > lock(m_Mutex);)
+        m_ExceptionHandler.clear();
+    }
+
+    /*!
+     * The method returns \c true if no filter is set or the attribute values pass the filter
+     *
+     * \param attrs A set of attribute values of a logging record
+     */
+    bool will_consume(attribute_value_set const& attrs)
+    {
+        BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);)
+        try
+        {
+            return m_Filter(attrs);
+        }
+#if !defined(BOOST_LOG_NO_THREADS)
+        catch (thread_interrupted&)
+        {
+            throw;
+        }
+#endif
+        catch (...)
+        {
+            if (m_ExceptionHandler.empty())
+                throw;
+            m_ExceptionHandler();
+            return false;
+        }
+    }
+
+protected:
+#if !defined(BOOST_LOG_NO_THREADS)
+    //! Returns reference to the frontend mutex
+    mutex_type& frontend_mutex() const { return m_Mutex; }
+#endif
+
+    //! Returns reference to the exception handler
+    exception_handler_type& exception_handler() { return m_ExceptionHandler; }
+    //! Returns reference to the exception handler
+    exception_handler_type const& exception_handler() const { return m_ExceptionHandler; }
+
+    //! Feeds log record to the backend
+    template< typename BackendMutexT, typename BackendT >
+    void feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
+    {
+        try
+        {
+            BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);)
+            backend.consume(rec);
+        }
+#if !defined(BOOST_LOG_NO_THREADS)
+        catch (thread_interrupted&)
+        {
+            throw;
+        }
+#endif
+        catch (...)
+        {
+            BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);)
+            if (m_ExceptionHandler.empty())
+                throw;
+            m_ExceptionHandler();
+        }
+    }
+
+    //! Attempts to feeds log record to the backend, does not block if \a backend_mutex is locked
+    template< typename BackendMutexT, typename BackendT >
+    bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
+    {
+#if !defined(BOOST_LOG_NO_THREADS)
+        unique_lock< BackendMutexT > lock;
+        try
+        {
+            unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock);
+            if (!tmp_lock.owns_lock())
+                return false;
+            lock.swap(tmp_lock);
+        }
+        catch (thread_interrupted&)
+        {
+            throw;
+        }
+        catch (...)
+        {
+            boost::log::aux::shared_lock_guard< mutex_type > frontend_lock(this->frontend_mutex());
+            if (this->exception_handler().empty())
+                throw;
+            this->exception_handler()();
+        }
+#endif
+        // No need to lock anything in the feed_record method
+        boost::log::aux::fake_mutex m;
+        feed_record(rec, m, backend);
+        return true;
+    }
+
+    //! Flushes record buffers in the backend, if one supports it
+    template< typename BackendMutexT, typename BackendT >
+    void flush_backend(BackendMutexT& backend_mutex, BackendT& backend)
+    {
+        typedef typename BackendT::frontend_requirements frontend_requirements;
+        flush_backend_impl(backend_mutex, backend,
+            typename has_requirement< frontend_requirements, flushing >::type());
+    }
+
+private:
+    //! Flushes record buffers in the backend (the actual implementation)
+    template< typename BackendMutexT, typename BackendT >
+    void flush_backend_impl(BackendMutexT& backend_mutex, BackendT& backend, mpl::true_)
+    {
+        try
+        {
+            BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);)
+            backend.flush();
+        }
+#if !defined(BOOST_LOG_NO_THREADS)
+        catch (thread_interrupted&)
+        {
+            throw;
+        }
+#endif
+        catch (...)
+        {
+            BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(m_Mutex);)
+            if (m_ExceptionHandler.empty())
+                throw;
+            m_ExceptionHandler();
+        }
+    }
+    //! Flushes record buffers in the backend (stub for backends that don't support flushing)
+    template< typename BackendMutexT, typename BackendT >
+    void flush_backend_impl(BackendMutexT&, BackendT&, mpl::false_)
+    {
+    }
+};
+
+//! A base class for a logging sink frontend with formatting support
+template< typename CharT >
+class BOOST_LOG_NO_VTABLE basic_formatting_sink_frontend :
+    public basic_sink_frontend
+{
+    typedef basic_sink_frontend base_type;
+
+public:
+    //! Character type
+    typedef CharT char_type;
+    //! Formatted string type
+    typedef std::basic_string< char_type > string_type;
+
+    //! Formatter function object type
+    typedef basic_formatter< char_type > formatter_type;
+    //! Output stream type
+    typedef typename formatter_type::stream_type stream_type;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+protected:
+    //! Mutex type
+    typedef typename base_type::mutex_type mutex_type;
+#endif
+
+private:
+    struct formatting_context
+    {
+#if !defined(BOOST_LOG_NO_THREADS)
+        //! Object version
+        const unsigned int m_Version;
+#endif
+        //! Formatted log record storage
+        string_type m_FormattedRecord;
+        //! Formatting stream
+        stream_type m_FormattingStream;
+        //! Formatter functor
+        formatter_type m_Formatter;
+
+        formatting_context() :
+#if !defined(BOOST_LOG_NO_THREADS)
+            m_Version(0),
+#endif
+            m_FormattingStream(m_FormattedRecord)
+        {
+            m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit);
+        }
+#if !defined(BOOST_LOG_NO_THREADS)
+        formatting_context(unsigned int version, std::locale const& loc, formatter_type const& formatter) :
+            m_Version(version),
+            m_FormattingStream(m_FormattedRecord),
+            m_Formatter(formatter)
+        {
+            m_FormattingStream.exceptions(std::ios_base::badbit | std::ios_base::failbit);
+            m_FormattingStream.imbue(loc);
+        }
+#endif
+    };
+
+private:
+#if !defined(BOOST_LOG_NO_THREADS)
+
+    //! State version
+    volatile unsigned int m_Version;
+
+    //! Formatter functor
+    formatter_type m_Formatter;
+    //! Locale to perform formatting
+    std::locale m_Locale;
+
+    //! Formatting state
+    thread_specific_ptr< formatting_context > m_pContext;
+
+#else
+
+    //! Formatting state
+    formatting_context m_Context;
+
+#endif // !defined(BOOST_LOG_NO_THREADS)
+
+public:
+    /*!
+     * \brief Initializing constructor
+     *
+     * \param cross_thread The flag indicates whether the sink passes log records between different threads
+     */
+    explicit basic_formatting_sink_frontend(bool cross_thread) :
+        basic_sink_frontend(cross_thread)
+#if !defined(BOOST_LOG_NO_THREADS)
+        , m_Version(0)
+#endif
+    {
+    }
+
+    /*!
+     * The method sets sink-specific formatter function object
+     */
+    template< typename FunT >
+    void set_formatter(FunT const& formatter)
+    {
+#if !defined(BOOST_LOG_NO_THREADS)
+        boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex());
+        m_Formatter = formatter;
+        ++m_Version;
+#else
+        m_Context.m_Formatter = formatter;
+#endif
+    }
+    /*!
+     * The method resets the formatter
+     */
+    void reset_formatter()
+    {
+#if !defined(BOOST_LOG_NO_THREADS)
+        boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex());
+        m_Formatter.reset();
+        ++m_Version;
+#else
+        m_Context.m_Formatter.reset();
+#endif
+    }
+
+    /*!
+     * The method returns the current locale used for formatting
+     */
+    std::locale getloc() const
+    {
+#if !defined(BOOST_LOG_NO_THREADS)
+        boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex());
+        return m_Locale;
+#else
+        return m_Context.m_FormattingStream.getloc();
+#endif
+    }
+    /*!
+     * The method sets the locale used for formatting
+     */
+    void imbue(std::locale const& loc)
+    {
+#if !defined(BOOST_LOG_NO_THREADS)
+        boost::log::aux::exclusive_lock_guard< mutex_type > lock(this->frontend_mutex());
+        m_Locale = loc;
+        ++m_Version;
+#else
+        m_Context.m_FormattingStream.imbue(loc);
+#endif
+    }
+
+protected:
+    //! Returns reference to the formatter
+    formatter_type& formatter()
+    {
+#if !defined(BOOST_LOG_NO_THREADS)
+        return m_Formatter;
+#else
+        return m_Context.m_Formatter;
+#endif
+    }
+
+    //! Feeds log record to the backend
+    template< typename BackendMutexT, typename BackendT >
+    void feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
+    {
+        formatting_context* context;
+
+#if !defined(BOOST_LOG_NO_THREADS)
+        context = m_pContext.get();
+        if (!context || context->m_Version != m_Version)
+        {
+            {
+                boost::log::aux::shared_lock_guard< mutex_type > lock(this->frontend_mutex());
+                context = new formatting_context(m_Version, m_Locale, m_Formatter);
+            }
+            m_pContext.reset(context);
+        }
+#else
+        context = &m_Context;
+#endif
+
+        boost::log::aux::cleanup_guard< stream_type > cleanup1(context->m_FormattingStream);
+        boost::log::aux::cleanup_guard< string_type > cleanup2(context->m_FormattedRecord);
+
+        try
+        {
+            // Perform the formatting
+            context->m_Formatter(rec, context->m_FormattingStream);
+            context->m_FormattingStream.flush();
+
+            // Feed the record
+            BOOST_LOG_EXPR_IF_MT(boost::log::aux::exclusive_lock_guard< BackendMutexT > lock(backend_mutex);)
+            backend.consume(rec, context->m_FormattedRecord);
+        }
+#if !defined(BOOST_LOG_NO_THREADS)
+        catch (thread_interrupted&)
+        {
+            throw;
+        }
+#endif
+        catch (...)
+        {
+            BOOST_LOG_EXPR_IF_MT(boost::log::aux::shared_lock_guard< mutex_type > lock(this->frontend_mutex());)
+            if (this->exception_handler().empty())
+                throw;
+            this->exception_handler()();
+        }
+    }
+
+    //! Attempts to feeds log record to the backend, does not block if \a backend_mutex is locked
+    template< typename BackendMutexT, typename BackendT >
+    bool try_feed_record(record_view const& rec, BackendMutexT& backend_mutex, BackendT& backend)
+    {
+#if !defined(BOOST_LOG_NO_THREADS)
+        unique_lock< BackendMutexT > lock;
+        try
+        {
+            unique_lock< BackendMutexT > tmp_lock(backend_mutex, try_to_lock);
+            if (!tmp_lock.owns_lock())
+                return false;
+            lock.swap(tmp_lock);
+        }
+        catch (thread_interrupted&)
+        {
+            throw;
+        }
+        catch (...)
+        {
+            boost::log::aux::shared_lock_guard< mutex_type > frontend_lock(this->frontend_mutex());
+            if (this->exception_handler().empty())
+                throw;
+            this->exception_handler()();
+        }
+#endif
+        // No need to lock anything in the feed_record method
+        boost::log::aux::fake_mutex m;
+        feed_record(rec, m, backend);
+        return true;
+    }
+};
+
+namespace aux {
+
+    template<
+        typename BackendT,
+        bool RequiresFormattingV = has_requirement<
+            typename BackendT::frontend_requirements,
+            formatted_records
+        >::value
+    >
+    struct make_sink_frontend_base
+    {
+        typedef basic_sink_frontend type;
+    };
+    template< typename BackendT >
+    struct make_sink_frontend_base< BackendT, true >
+    {
+        typedef basic_formatting_sink_frontend< typename BackendT::char_type > type;
+    };
+
+} // namespace aux
+
+} // namespace sinks
+
+BOOST_LOG_CLOSE_NAMESPACE // namespace log
+
+} // namespace boost
+
+#include <boost/log/detail/footer.hpp>
+
+#endif // BOOST_LOG_SINKS_BASIC_SINK_FRONTEND_HPP_INCLUDED_