1 /* 2 * Copyright Andrey Semashev 2007 - 2015. 3 * Distributed under the Boost Software License, Version 1.0. 4 * (See accompanying file LICENSE_1_0.txt or copy at 5 * http://www.boost.org/LICENSE_1_0.txt) 6 */ 7 /*! 8 * \file sync_frontend.hpp 9 * \author Andrey Semashev 10 * \date 14.07.2009 11 * 12 * The header contains implementation of synchronous sink frontend. 13 */ 14 15 #ifndef BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_ 16 #define BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_ 17 18 #include <boost/log/detail/config.hpp> 19 20 #ifdef BOOST_HAS_PRAGMA_ONCE 21 #pragma once 22 #endif 23 24 #if defined(BOOST_LOG_NO_THREADS) 25 #error Boost.Log: Synchronous sink frontend is only supported in multithreaded environment 26 #endif 27 28 #include <boost/static_assert.hpp> 29 #include <boost/smart_ptr/shared_ptr.hpp> 30 #include <boost/smart_ptr/make_shared_object.hpp> 31 #include <boost/preprocessor/control/if.hpp> 32 #include <boost/preprocessor/comparison/equal.hpp> 33 #include <boost/thread/recursive_mutex.hpp> 34 #include <boost/log/detail/locking_ptr.hpp> 35 #include <boost/log/detail/parameter_tools.hpp> 36 #include <boost/log/core/record_view.hpp> 37 #include <boost/log/sinks/basic_sink_frontend.hpp> 38 #include <boost/log/sinks/frontend_requirements.hpp> 39 #include <boost/log/detail/header.hpp> 40 41 namespace boost { 42 43 BOOST_LOG_OPEN_NAMESPACE 44 45 namespace sinks { 46 47 #ifndef BOOST_LOG_DOXYGEN_PASS 48 49 #define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1(n, data)\ 50 template< typename T0 >\ 51 explicit synchronous_sink(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\ 52 base_type(false),\ 53 m_pBackend(boost::make_shared< sink_backend_type >(arg0)) {} 54 55 #define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N(n, data)\ 56 template< BOOST_PP_ENUM_PARAMS(n, typename T) >\ 57 explicit synchronous_sink(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg)) :\ 58 base_type(false),\ 59 m_pBackend(boost::make_shared< sink_backend_type >(BOOST_PP_ENUM_PARAMS(n, arg))) {} 60 61 #define BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL(z, n, data)\ 62 BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1, BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N)(n, data) 63 64 #endif // BOOST_LOG_DOXYGEN_PASS 65 66 /*! 67 * \brief Synchronous logging sink frontend 68 * 69 * The sink frontend serializes threads before passing logging records to the backend 70 */ 71 template< typename SinkBackendT > 72 class synchronous_sink : 73 public aux::make_sink_frontend_base< SinkBackendT >::type 74 { 75 typedef typename aux::make_sink_frontend_base< SinkBackendT >::type base_type; 76 77 private: 78 //! Synchronization mutex type 79 typedef boost::recursive_mutex backend_mutex_type; 80 81 public: 82 //! Sink implementation type 83 typedef SinkBackendT sink_backend_type; 84 //! \cond 85 BOOST_STATIC_ASSERT_MSG((has_requirement< typename sink_backend_type::frontend_requirements, synchronized_feeding >::value), "Synchronous sink frontend is incompatible with the specified backend: thread synchronization requirements are not met"); 86 //! \endcond 87 88 #ifndef BOOST_LOG_DOXYGEN_PASS 89 90 //! A pointer type that locks the backend until it's destroyed 91 typedef boost::log::aux::locking_ptr< sink_backend_type, backend_mutex_type > locked_backend_ptr; 92 93 #else // BOOST_LOG_DOXYGEN_PASS 94 95 //! A pointer type that locks the backend until it's destroyed 96 typedef implementation_defined locked_backend_ptr; 97 98 #endif // BOOST_LOG_DOXYGEN_PASS 99 100 private: 101 //! Synchronization mutex 102 backend_mutex_type m_BackendMutex; 103 //! Pointer to the backend 104 const shared_ptr< sink_backend_type > m_pBackend; 105 106 public: 107 /*! 108 * Default constructor. Constructs the sink backend instance. 109 * Requires the backend to be default-constructible. 110 */ synchronous_sink()111 synchronous_sink() : 112 base_type(false), 113 m_pBackend(boost::make_shared< sink_backend_type >()) 114 { 115 } 116 /*! 117 * Constructor attaches user-constructed backend instance 118 * 119 * \param backend Pointer to the backend instance 120 * 121 * \pre \a backend is not \c NULL. 122 */ synchronous_sink(shared_ptr<sink_backend_type> const & backend)123 explicit synchronous_sink(shared_ptr< sink_backend_type > const& backend) : 124 base_type(false), 125 m_pBackend(backend) 126 { 127 } 128 129 /*! 130 * Constructor that passes arbitrary named parameters to the interprocess sink backend constructor. 131 * Refer to the backend documentation for the list of supported parameters. 132 */ 133 #ifndef BOOST_LOG_DOXYGEN_PASS 134 BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL, ~) 135 #else 136 template< typename... Args > 137 explicit synchronous_sink(Args&&... args); 138 #endif 139 140 /*! 141 * Locking accessor to the attached backend 142 */ locked_backend()143 locked_backend_ptr locked_backend() 144 { 145 return locked_backend_ptr(m_pBackend, m_BackendMutex); 146 } 147 148 /*! 149 * Passes the log record to the backend 150 */ consume(record_view const & rec)151 void consume(record_view const& rec) BOOST_OVERRIDE 152 { 153 base_type::feed_record(rec, m_BackendMutex, *m_pBackend); 154 } 155 156 /*! 157 * The method attempts to pass logging record to the backend 158 */ try_consume(record_view const & rec)159 bool try_consume(record_view const& rec) BOOST_OVERRIDE 160 { 161 return base_type::try_feed_record(rec, m_BackendMutex, *m_pBackend); 162 } 163 164 /*! 165 * The method performs flushing of any internal buffers that may hold log records. The method 166 * may take considerable time to complete and may block both the calling thread and threads 167 * attempting to put new records into the sink while this call is in progress. 168 */ flush()169 void flush() BOOST_OVERRIDE 170 { 171 base_type::flush_backend(m_BackendMutex, *m_pBackend); 172 } 173 }; 174 175 #undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_1 176 #undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL_N 177 #undef BOOST_LOG_SINK_CTOR_FORWARD_INTERNAL 178 179 } // namespace sinks 180 181 BOOST_LOG_CLOSE_NAMESPACE // namespace log 182 183 } // namespace boost 184 185 #include <boost/log/detail/footer.hpp> 186 187 #endif // BOOST_LOG_SINKS_SYNC_FRONTEND_HPP_INCLUDED_ 188