• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   block_on_overflow.hpp
9  * \author Andrey Semashev
10  * \date   04.01.2012
11  *
12  * The header contains implementation of \c block_on_overflow strategy for handling
13  * queue overflows in bounded queues for the asynchronous sink frontend.
14  */
15 
16 #ifndef BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_
17 #define BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_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/intrusive/options.hpp>
30 #include <boost/intrusive/list.hpp>
31 #include <boost/intrusive/list_hook.hpp>
32 #include <boost/thread/condition_variable.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 Blocking strategy for handling log record queue overflows
44  *
45  * This strategy will cause enqueueing threads to block when the
46  * log record queue overflows. The blocked threads will be woken as
47  * soon as there appears free space in the queue, in the same order
48  * they attempted to enqueue records.
49  */
50 class block_on_overflow
51 {
52 #ifndef BOOST_LOG_DOXYGEN_PASS
53 private:
54     typedef intrusive::list_base_hook<
55         intrusive::link_mode< intrusive::auto_unlink >
56     > thread_context_hook_t;
57 
58     struct thread_context :
59         public thread_context_hook_t
60     {
61         condition_variable cond;
62         bool result;
63 
thread_contextboost::sinks::block_on_overflow::thread_context64         thread_context() : result(true) {}
65     };
66 
67     typedef intrusive::list<
68         thread_context,
69         intrusive::base_hook< thread_context_hook_t >,
70         intrusive::constant_time_size< false >
71     > thread_contexts;
72 
73 private:
74     //! Blocked threads
75     thread_contexts m_thread_contexts;
76 
77 public:
78     /*!
79      * Default constructor.
80      */
block_on_overflow()81     BOOST_DEFAULTED_FUNCTION(block_on_overflow(), {})
82 
83     /*!
84      * This method is called by the queue when overflow is detected.
85      *
86      * \param lock An internal lock that protects the queue
87      *
88      * \retval true Attempt to enqueue the record again.
89      * \retval false Discard the record.
90      */
91     template< typename LockT >
92     bool on_overflow(record_view const&, LockT& lock)
93     {
94         thread_context context;
95         m_thread_contexts.push_back(context);
96         do
97         {
98             context.cond.wait(lock);
99         }
100         while (context.is_linked());
101 
102         return context.result;
103     }
104 
105     /*!
106      * This method is called by the queue when there appears a free space.
107      * The internal lock protecting the queue is locked when calling this method.
108      */
on_queue_space_available()109     void on_queue_space_available()
110     {
111         if (!m_thread_contexts.empty())
112         {
113             m_thread_contexts.front().cond.notify_one();
114             m_thread_contexts.pop_front();
115         }
116     }
117 
118     /*!
119      * This method is called by the queue to interrupt any possible waits in \c on_overflow.
120      * The internal lock protecting the queue is locked when calling this method.
121      */
interrupt()122     void interrupt()
123     {
124         while (!m_thread_contexts.empty())
125         {
126             thread_context& context = m_thread_contexts.front();
127             context.result = false;
128             context.cond.notify_one();
129             m_thread_contexts.pop_front();
130         }
131     }
132 
133     //  Copying prohibited
134     BOOST_DELETED_FUNCTION(block_on_overflow(block_on_overflow const&))
135     BOOST_DELETED_FUNCTION(block_on_overflow& operator= (block_on_overflow const&))
136 #endif // BOOST_LOG_DOXYGEN_PASS
137 };
138 
139 } // namespace sinks
140 
141 BOOST_LOG_CLOSE_NAMESPACE // namespace log
142 
143 } // namespace boost
144 
145 #include <boost/log/detail/footer.hpp>
146 
147 #endif // BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_
148