You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
5.4 KiB

  1. // -*- C++ -*-
  2. // Copyright (C) 2009-2010, Vaclav Haisman. All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without modifica-
  5. // tion, are permitted provided that the following conditions are met:
  6. //
  7. // 1. Redistributions of source code must retain the above copyright notice,
  8. // this list of conditions and the following disclaimer.
  9. //
  10. // 2. Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. //
  14. // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  15. // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  16. // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  17. // APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  18. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
  19. // DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  20. // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  21. // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. #ifndef LOG4CPLUS_HELPERS_QUEUE_H
  25. #define LOG4CPLUS_HELPERS_QUEUE_H
  26. #include <log4cplus/config.hxx>
  27. #if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE)
  28. #pragma once
  29. #endif
  30. #if ! defined (LOG4CPLUS_SINGLE_THREADED)
  31. #include <deque>
  32. #include <log4cplus/spi/loggingevent.h>
  33. #include <log4cplus/thread/threads.h>
  34. #include <log4cplus/thread/syncprims.h>
  35. namespace log4cplus { namespace thread {
  36. //! Single consumer, multiple producers queue.
  37. class LOG4CPLUS_EXPORT Queue
  38. : public virtual helpers::SharedObject
  39. {
  40. public:
  41. //! Type of the state flags field.
  42. typedef unsigned flags_type;
  43. //! Queue storage type.
  44. typedef std::deque<spi::InternalLoggingEvent> queue_storage_type;
  45. Queue (unsigned len = 100);
  46. virtual ~Queue ();
  47. // Producers' methods.
  48. //! Puts event <code>ev</code> into queue, sets QUEUE flag and
  49. //! sets internal event object into signaled state. If the EXIT
  50. //! flags is already set upon entering the function, nothing is
  51. //! inserted into the queue. The function can block on internal
  52. //! semaphore if the queue has reached maximal allowed
  53. //! length. Calling thread is unblocked either by consumer thread
  54. //! removing item from queue or by any other thread calling
  55. //! signal_exit().
  56. //!
  57. //! \param ev spi::InternalLoggingEvent to be put into the queue.
  58. //! \return Flags.
  59. flags_type put_event (spi::InternalLoggingEvent const & ev);
  60. //! Sets EXIT flag and DRAIN flag and sets internal event object
  61. //! into signaled state.
  62. //! \param drain If true, DRAIN flag will be set, otherwise unset.
  63. //! \return Flags, ERROR_BIT can be set upon error.
  64. flags_type signal_exit (bool drain = true);
  65. // Consumer's methods.
  66. //! The get_events() function is used by queue's consumer. It
  67. //! fills <code>buf</code> argument and sets EVENT flag in return
  68. //! value. If EXIT flag is already set in flags member upon
  69. //! entering the function then depending on DRAIN flag it either
  70. //! fills <code>buf</code> argument or does not fill the argument,
  71. //! if the queue is non-empty. The function blocks by waiting for
  72. //! internal event object to be signaled if the queue is empty,
  73. //! unless EXIT flag is set. The calling thread is unblocked when
  74. //! items are added into the queue or when exit is signaled using
  75. //! the signal_exit() function.
  76. //!
  77. //!
  78. //! Upon error, return value has one of the error flags set.
  79. //!
  80. //! \param buf Pointer to storage of spi::InternalLoggingEvent
  81. //! instances to be filled from queue.
  82. //! \return Flags.
  83. flags_type get_events (queue_storage_type * buf);
  84. //! Possible state flags.
  85. enum Flags
  86. {
  87. //! EVENT flag is set in return value of get_event() call if
  88. //! the <code>ev</code> argument is filled with event from the queue.
  89. EVENT = 0x0001,
  90. //! QUEUE flag is set by producers when they put item into the
  91. //! queue.
  92. QUEUE = 0x0002,
  93. //! EXIT flag is set by signal_exit() call, signaling that the
  94. //! queue worker thread should end itself.
  95. EXIT = 0x0004,
  96. //! When DRAIN flag is set together with EXIT flag, the queue
  97. //! worker thread will first drain the queue before exiting.
  98. DRAIN = 0x0008,
  99. //! ERROR_BIT signals error.
  100. ERROR_BIT = 0x0010,
  101. //! ERROR_AFTER signals error that has occured after queue has
  102. //! already been touched.
  103. ERROR_AFTER = 0x0020
  104. };
  105. protected:
  106. //! Queue storage.
  107. queue_storage_type queue;
  108. //! Mutex protecting queue and flags.
  109. Mutex mutex;
  110. //! Event on which consumer can wait if it finds queue empty.
  111. ManualResetEvent ev_consumer;
  112. //! Semaphore that limits the queue length.
  113. Semaphore sem;
  114. //! State flags.
  115. flags_type flags;
  116. private:
  117. Queue (Queue const &);
  118. Queue & operator = (Queue const &);
  119. };
  120. typedef helpers::SharedObjectPtr<Queue> QueuePtr;
  121. } } // namespace log4cplus { namespace thread {
  122. #endif // LOG4CPLUS_SINGLE_THREADED
  123. #endif // LOG4CPLUS_HELPERS_QUEUE_H