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