]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/log/include/boost/log/sinks/bounded_fifo_queue.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / log / include / boost / log / sinks / bounded_fifo_queue.hpp
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 bounded_fifo_queue.hpp
9 * \author Andrey Semashev
10 * \date 04.01.2012
11 *
12 * The header contains implementation of bounded FIFO queueing strategy for
13 * the asynchronous sink frontend.
14 */
15
16 #ifndef BOOST_LOG_SINKS_BOUNDED_FIFO_QUEUE_HPP_INCLUDED_
17 #define BOOST_LOG_SINKS_BOUNDED_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 <cstddef>
30 #include <queue>
31 #include <boost/thread/locks.hpp>
32 #include <boost/thread/mutex.hpp>
33 #include <boost/thread/condition_variable.hpp>
34 #include <boost/log/core/record_view.hpp>
35 #include <boost/log/detail/header.hpp>
36
37 namespace boost {
38
39 BOOST_LOG_OPEN_NAMESPACE
40
41 namespace sinks {
42
43 /*!
44 * \brief Bounded FIFO log record queueing strategy
45 *
46 * The \c bounded_fifo_queue class is intended to be used with
47 * the \c asynchronous_sink frontend as a log record queueing strategy.
48 *
49 * This strategy describes log record queueing logic.
50 * The queue has a limited capacity, upon reaching which the enqueue operation will
51 * invoke the overflow handling strategy specified in the \c OverflowStrategyT
52 * template parameter to handle the situation. The library provides overflow handling
53 * strategies for most common cases: \c drop_on_overflow will silently discard the log record,
54 * and \c block_on_overflow will put the enqueueing thread to wait until there is space
55 * in the queue.
56 *
57 * The log record queue imposes no ordering over the queued
58 * elements aside from the order in which they are enqueued.
59 */
60 template< std::size_t MaxQueueSizeV, typename OverflowStrategyT >
61 class bounded_fifo_queue :
62 private OverflowStrategyT
63 {
64 private:
65 typedef OverflowStrategyT overflow_strategy;
66 typedef std::queue< record_view > queue_type;
67 typedef boost::mutex mutex_type;
68
69 private:
70 //! Synchronization primitive
71 mutex_type m_mutex;
72 //! Condition to block the consuming thread on
73 condition_variable m_cond;
74 //! Log record queue
75 queue_type m_queue;
76 //! Interruption flag
77 bool m_interruption_requested;
78
79 protected:
80 //! Default constructor
81 bounded_fifo_queue() : m_interruption_requested(false)
82 {
83 }
84 //! Initializing constructor
85 template< typename ArgsT >
86 explicit bounded_fifo_queue(ArgsT const&) : m_interruption_requested(false)
87 {
88 }
89
90 //! Enqueues log record to the queue
91 void enqueue(record_view const& rec)
92 {
93 unique_lock< mutex_type > lock(m_mutex);
94 std::size_t size = m_queue.size();
95 for (; size >= MaxQueueSizeV; size = m_queue.size())
96 {
97 if (!overflow_strategy::on_overflow(rec, lock))
98 return;
99 }
100
101 m_queue.push(rec);
102 if (size == 0)
103 m_cond.notify_one();
104 }
105
106 //! Attempts to enqueue log record to the queue
107 bool try_enqueue(record_view const& rec)
108 {
109 unique_lock< mutex_type > lock(m_mutex, try_to_lock);
110 if (lock.owns_lock())
111 {
112 const std::size_t size = m_queue.size();
113
114 // Do not invoke the bounding strategy in case of overflow as it may block
115 if (size < MaxQueueSizeV)
116 {
117 m_queue.push(rec);
118 if (size == 0)
119 m_cond.notify_one();
120 return true;
121 }
122 }
123
124 return false;
125 }
126
127 //! Attempts to dequeue a log record ready for processing from the queue, does not block if the queue is empty
128 bool try_dequeue_ready(record_view& rec)
129 {
130 return try_dequeue(rec);
131 }
132
133 //! Attempts to dequeue log record from the queue, does not block if the queue is empty
134 bool try_dequeue(record_view& rec)
135 {
136 lock_guard< mutex_type > lock(m_mutex);
137 const std::size_t size = m_queue.size();
138 if (size > 0)
139 {
140 rec.swap(m_queue.front());
141 m_queue.pop();
142 overflow_strategy::on_queue_space_available();
143 return true;
144 }
145
146 return false;
147 }
148
149 //! Dequeues log record from the queue, blocks if the queue is empty
150 bool dequeue_ready(record_view& rec)
151 {
152 unique_lock< mutex_type > lock(m_mutex);
153
154 while (!m_interruption_requested)
155 {
156 const std::size_t size = m_queue.size();
157 if (size > 0)
158 {
159 rec.swap(m_queue.front());
160 m_queue.pop();
161 overflow_strategy::on_queue_space_available();
162 return true;
163 }
164 else
165 {
166 m_cond.wait(lock);
167 }
168 }
169 m_interruption_requested = false;
170
171 return false;
172 }
173
174 //! Wakes a thread possibly blocked in the \c dequeue method
175 void interrupt_dequeue()
176 {
177 lock_guard< mutex_type > lock(m_mutex);
178 m_interruption_requested = true;
179 overflow_strategy::interrupt();
180 m_cond.notify_one();
181 }
182 };
183
184 } // namespace sinks
185
186 BOOST_LOG_CLOSE_NAMESPACE // namespace log
187
188 } // namespace boost
189
190 #include <boost/log/detail/footer.hpp>
191
192 #endif // BOOST_LOG_SINKS_BOUNDED_FIFO_QUEUE_HPP_INCLUDED_