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 unbounded_fifo_queue.hpp 9 * \author Andrey Semashev 10 * \date 24.07.2011 11 * 12 * The header contains implementation of unbounded FIFO queueing strategy for 13 * the asynchronous sink frontend. 14 */ 15 16 #ifndef BOOST_LOG_SINKS_UNBOUNDED_FIFO_QUEUE_HPP_INCLUDED_ 17 #define BOOST_LOG_SINKS_UNBOUNDED_FIFO_QUEUE_HPP_INCLUDED_ 18 19 #include <boost/log/detail/config.hpp> 20 21 #ifdef BOOST_HAS_PRAGMA_ONCE 22 #pragma once 23 #endif 24 25 #if defined(BOOST_LOG_NO_THREADS) 26 #error Boost.Log: This header content is only supported in multithreaded environment 27 #endif 28 29 #include <boost/memory_order.hpp> 30 #include <boost/atomic/atomic.hpp> 31 #include <boost/log/detail/event.hpp> 32 #include <boost/log/detail/threadsafe_queue.hpp> 33 #include <boost/log/core/record_view.hpp> 34 #include <boost/log/detail/header.hpp> 35 36 namespace boost { 37 38 BOOST_LOG_OPEN_NAMESPACE 39 40 namespace sinks { 41 42 /*! 43 * \brief Unbounded FIFO log record queueing strategy 44 * 45 * The \c unbounded_fifo_queue class is intended to be used with 46 * the \c asynchronous_sink frontend as a log record queueing strategy. 47 * 48 * This strategy implements the simplest logic of log record buffering between 49 * threads: the queue has no limits and imposes no ordering over the queued 50 * elements aside from the order in which they are enqueued. 51 * Because of this the queue provides decent performance and scalability, 52 * however if sink backends can't consume log records fast enough the queue 53 * may grow uncontrollably. When this is an issue, it is recommended to 54 * use one of the bounded strategies. 55 */ 56 class unbounded_fifo_queue 57 { 58 private: 59 typedef boost::log::aux::threadsafe_queue< record_view > queue_type; 60 61 private: 62 //! Thread-safe queue 63 queue_type m_queue; 64 //! Event object to block on 65 boost::log::aux::event m_event; 66 //! Interruption flag 67 boost::atomic< bool > m_interruption_requested; 68 69 protected: 70 //! Default constructor unbounded_fifo_queue()71 unbounded_fifo_queue() : m_interruption_requested(false) 72 { 73 } 74 //! Initializing constructor 75 template< typename ArgsT > unbounded_fifo_queue(ArgsT const &)76 explicit unbounded_fifo_queue(ArgsT const&) : m_interruption_requested(false) 77 { 78 } 79 80 //! Enqueues log record to the queue enqueue(record_view const & rec)81 void enqueue(record_view const& rec) 82 { 83 m_queue.push(rec); 84 m_event.set_signalled(); 85 } 86 87 //! Attempts to enqueue log record to the queue try_enqueue(record_view const & rec)88 bool try_enqueue(record_view const& rec) 89 { 90 // Assume the call never blocks 91 enqueue(rec); 92 return true; 93 } 94 95 //! Attempts to dequeue a log record ready for processing from the queue, does not block if the queue is empty try_dequeue_ready(record_view & rec)96 bool try_dequeue_ready(record_view& rec) 97 { 98 return m_queue.try_pop(rec); 99 } 100 101 //! Attempts to dequeue log record from the queue, does not block if the queue is empty try_dequeue(record_view & rec)102 bool try_dequeue(record_view& rec) 103 { 104 return m_queue.try_pop(rec); 105 } 106 107 //! Dequeues log record from the queue, blocks if the queue is empty dequeue_ready(record_view & rec)108 bool dequeue_ready(record_view& rec) 109 { 110 // Try the fast way first 111 if (m_queue.try_pop(rec)) 112 return true; 113 114 // Ok, we probably have to wait for new records 115 while (true) 116 { 117 m_event.wait(); 118 if (m_interruption_requested.exchange(false, boost::memory_order_acquire)) 119 return false; 120 if (m_queue.try_pop(rec)) 121 return true; 122 } 123 } 124 125 //! Wakes a thread possibly blocked in the \c dequeue method interrupt_dequeue()126 void interrupt_dequeue() 127 { 128 m_interruption_requested.store(true, boost::memory_order_release); 129 m_event.set_signalled(); 130 } 131 }; 132 133 } // namespace sinks 134 135 BOOST_LOG_CLOSE_NAMESPACE // namespace log 136 137 } // namespace boost 138 139 #include <boost/log/detail/footer.hpp> 140 141 #endif // BOOST_LOG_SINKS_UNBOUNDED_FIFO_QUEUE_HPP_INCLUDED_ 142