text_ipc_message_queue_backend.hpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright Lingxi Li 2015.
  3. * Copyright Andrey Semashev 2016.
  4. * Distributed under the Boost Software License, Version 1.0.
  5. * (See accompanying file LICENSE_1_0.txt or copy at
  6. * http://www.boost.org/LICENSE_1_0.txt)
  7. */
  8. /*!
  9. * \file text_ipc_message_queue_backend.hpp
  10. * \author Lingxi Li
  11. * \author Andrey Semashev
  12. * \date 14.10.2015
  13. *
  14. * The header contains implementation of a text interprocess message queue sink
  15. * backend along with implementation of a supporting interprocess message queue.
  16. */
  17. #ifndef BOOST_LOG_SINKS_TEXT_IPC_MESSAGE_QUEUE_BACKEND_HPP_INCLUDED_
  18. #define BOOST_LOG_SINKS_TEXT_IPC_MESSAGE_QUEUE_BACKEND_HPP_INCLUDED_
  19. #include <limits>
  20. #include <string>
  21. #include <boost/cstdint.hpp>
  22. #include <boost/move/core.hpp>
  23. #include <boost/preprocessor/control/if.hpp>
  24. #include <boost/preprocessor/comparison/equal.hpp>
  25. #include <boost/log/detail/config.hpp>
  26. #include <boost/log/detail/parameter_tools.hpp>
  27. #include <boost/log/core/record_view.hpp>
  28. #include <boost/log/sinks/basic_sink_backend.hpp>
  29. #include <boost/log/sinks/frontend_requirements.hpp>
  30. #include <boost/log/exceptions.hpp>
  31. #include <boost/log/detail/header.hpp>
  32. #ifdef BOOST_HAS_PRAGMA_ONCE
  33. #pragma once
  34. #endif
  35. namespace boost {
  36. BOOST_LOG_OPEN_NAMESPACE
  37. namespace sinks {
  38. #ifndef BOOST_LOG_DOXYGEN_PASS
  39. #define BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_1(z, n, data)\
  40. template< typename T0 >\
  41. explicit text_ipc_message_queue_backend(T0 const& arg0, typename boost::log::aux::enable_if_named_parameters< T0, boost::log::aux::sfinae_dummy >::type = boost::log::aux::sfinae_dummy()) :\
  42. m_queue(arg0) {}
  43. #define BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_N(z, n, data)\
  44. template< BOOST_PP_ENUM_PARAMS_Z(z, n, typename T) >\
  45. explicit text_ipc_message_queue_backend(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, T, const& arg)) :\
  46. m_queue(BOOST_PP_ENUM_PARAMS_Z(z, n, arg)) {}
  47. #define BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL(z, n, data)\
  48. BOOST_PP_IF(BOOST_PP_EQUAL(n, 1), BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_1, BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_N)(z, n, data)
  49. #endif // BOOST_LOG_DOXYGEN_PASS
  50. /*!
  51. * \brief An implementation of a text interprocess message queue sink backend and
  52. * a supporting interprocess message queue.
  53. *
  54. * The sink backend sends formatted log messages to an interprocess message queue
  55. * which can be extracted by a viewer process. Methods of this class are not
  56. * thread-safe, unless otherwise specified.
  57. */
  58. template< typename QueueT >
  59. class text_ipc_message_queue_backend :
  60. public basic_formatted_sink_backend< char, concurrent_feeding >
  61. {
  62. //! Base type
  63. typedef basic_formatted_sink_backend< char, concurrent_feeding > base_type;
  64. public:
  65. //! Character type
  66. typedef base_type::char_type char_type;
  67. //! String type to be used as a message text holder
  68. typedef base_type::string_type string_type;
  69. //! Interprocess message queue type
  70. typedef QueueT queue_type;
  71. private:
  72. //! Interprocess queue
  73. queue_type m_queue;
  74. public:
  75. /*!
  76. * Default constructor. The method constructs the backend using the default-constructed
  77. * interprocess message queue. The queue may need additional setup in order to be able
  78. * to send messages.
  79. */
  80. text_ipc_message_queue_backend() BOOST_NOEXCEPT
  81. {
  82. }
  83. /*!
  84. * Initializing constructor. The method constructs the backend using the provided
  85. * interprocess message queue. The constructor moves from the provided queue.
  86. */
  87. explicit text_ipc_message_queue_backend(BOOST_RV_REF(queue_type) queue) BOOST_NOEXCEPT :
  88. m_queue(static_cast< BOOST_RV_REF(queue_type) >(queue))
  89. {
  90. }
  91. /*!
  92. * Constructor that passes arbitrary named parameters to the interprocess queue constructor.
  93. * Refer to the queue documentation for the list of supported parameters.
  94. */
  95. #ifndef BOOST_LOG_DOXYGEN_PASS
  96. BOOST_LOG_PARAMETRIZED_CONSTRUCTORS_GEN(BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL, ~)
  97. #else
  98. template< typename... Args >
  99. explicit text_ipc_message_queue_backend(Args&&... args);
  100. #endif
  101. /*!
  102. * The method returns a reference to the managed \c queue_type object.
  103. *
  104. * \return A reference to the managed \c queue_type object.
  105. */
  106. queue_type& message_queue() BOOST_NOEXCEPT { return m_queue; }
  107. /*!
  108. * The method returns a constant reference to the managed \c queue_type object.
  109. *
  110. * \return A constant reference to the managed \c queue_type object.
  111. */
  112. queue_type const& message_queue() const BOOST_NOEXCEPT { return m_queue; }
  113. /*!
  114. * Tests whether the object is associated with any message queue. Only when the backend has
  115. * an associated message queue, will any message be sent.
  116. *
  117. * \return \c true if the object is associated with a message queue, and \c false otherwise.
  118. */
  119. bool is_open() const BOOST_NOEXCEPT { return m_queue.is_open(); }
  120. /*!
  121. * The method writes the message to the backend. Concurrent calls to this method
  122. * are allowed. Therefore, the backend may be used with unlocked frontend. <tt>stop_local()</tt>
  123. * can be used to have a blocked <tt>consume()</tt> call return and prevent future
  124. * calls to <tt>consume()</tt> from blocking.
  125. */
  126. void consume(record_view const&, string_type const& formatted_message)
  127. {
  128. if (m_queue.is_open())
  129. {
  130. typedef typename queue_type::size_type size_type;
  131. const string_type::size_type size = formatted_message.size();
  132. if (BOOST_UNLIKELY(size > static_cast< string_type::size_type >((std::numeric_limits< size_type >::max)())))
  133. BOOST_LOG_THROW_DESCR(limitation_error, "Message too long to send to an interprocess queue");
  134. m_queue.send(formatted_message.data(), static_cast< size_type >(size));
  135. }
  136. }
  137. };
  138. #undef BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_1
  139. #undef BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL_N
  140. #undef BOOST_LOG_IPC_BACKEND_CTOR_FORWARD_INTERNAL
  141. } // namespace sinks
  142. BOOST_LOG_CLOSE_NAMESPACE // namespace log
  143. } // namespace boost
  144. #include <boost/log/detail/footer.hpp>
  145. #endif // BOOST_LOG_SINKS_TEXT_IPC_MESSAGE_QUEUE_BACKEND_HPP_INCLUDED_