unbounded_fifo_queue.hpp 3.9 KB

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