block_on_overflow.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. #ifndef BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_
  16. #define BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_
  17. #include <boost/log/detail/config.hpp>
  18. #ifdef BOOST_HAS_PRAGMA_ONCE
  19. #pragma once
  20. #endif
  21. #if defined(BOOST_LOG_NO_THREADS)
  22. #error Boost.Log: This header content is only supported in multithreaded environment
  23. #endif
  24. #include <boost/intrusive/options.hpp>
  25. #include <boost/intrusive/list.hpp>
  26. #include <boost/intrusive/list_hook.hpp>
  27. #include <boost/thread/condition_variable.hpp>
  28. #include <boost/log/core/record_view.hpp>
  29. #include <boost/log/detail/header.hpp>
  30. namespace boost {
  31. BOOST_LOG_OPEN_NAMESPACE
  32. namespace sinks {
  33. /*!
  34. * \brief Blocking strategy for handling log record queue overflows
  35. *
  36. * This strategy will cause enqueueing threads to block when the
  37. * log record queue overflows. The blocked threads will be woken as
  38. * soon as there appears free space in the queue, in the same order
  39. * they attempted to enqueue records.
  40. */
  41. class block_on_overflow
  42. {
  43. #ifndef BOOST_LOG_DOXYGEN_PASS
  44. private:
  45. typedef intrusive::list_base_hook<
  46. intrusive::link_mode< intrusive::auto_unlink >
  47. > thread_context_hook_t;
  48. struct thread_context :
  49. public thread_context_hook_t
  50. {
  51. condition_variable cond;
  52. bool result;
  53. thread_context() : result(true) {}
  54. };
  55. typedef intrusive::list<
  56. thread_context,
  57. intrusive::base_hook< thread_context_hook_t >,
  58. intrusive::constant_time_size< false >
  59. > thread_contexts;
  60. private:
  61. //! Blocked threads
  62. thread_contexts m_thread_contexts;
  63. public:
  64. /*!
  65. * Default constructor.
  66. */
  67. BOOST_DEFAULTED_FUNCTION(block_on_overflow(), {})
  68. /*!
  69. * This method is called by the queue when overflow is detected.
  70. *
  71. * \param lock An internal lock that protects the queue
  72. *
  73. * \retval true Attempt to enqueue the record again.
  74. * \retval false Discard the record.
  75. */
  76. template< typename LockT >
  77. bool on_overflow(record_view const&, LockT& lock)
  78. {
  79. thread_context context;
  80. m_thread_contexts.push_back(context);
  81. do
  82. {
  83. context.cond.wait(lock);
  84. }
  85. while (context.is_linked());
  86. return context.result;
  87. }
  88. /*!
  89. * This method is called by the queue when there appears a free space.
  90. * The internal lock protecting the queue is locked when calling this method.
  91. */
  92. void on_queue_space_available()
  93. {
  94. if (!m_thread_contexts.empty())
  95. {
  96. m_thread_contexts.front().cond.notify_one();
  97. m_thread_contexts.pop_front();
  98. }
  99. }
  100. /*!
  101. * This method is called by the queue to interrupt any possible waits in \c on_overflow.
  102. * The internal lock protecting the queue is locked when calling this method.
  103. */
  104. void interrupt()
  105. {
  106. while (!m_thread_contexts.empty())
  107. {
  108. thread_context& context = m_thread_contexts.front();
  109. context.result = false;
  110. context.cond.notify_one();
  111. m_thread_contexts.pop_front();
  112. }
  113. }
  114. // Copying prohibited
  115. BOOST_DELETED_FUNCTION(block_on_overflow(block_on_overflow const&))
  116. BOOST_DELETED_FUNCTION(block_on_overflow& operator= (block_on_overflow const&))
  117. #endif // BOOST_LOG_DOXYGEN_PASS
  118. };
  119. } // namespace sinks
  120. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  121. } // namespace boost
  122. #include <boost/log/detail/footer.hpp>
  123. #endif // BOOST_LOG_SINKS_BLOCK_ON_OVERFLOW_HPP_INCLUDED_