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.

188 lines
4.8 KiB

  1. // Copyright (C) 2009-2010, Vaclav Haisman. All rights reserved.
  2. //
  3. // Redistribution and use in source and binary forms, with or without modifica-
  4. // tion, are permitted provided that the following conditions are met:
  5. //
  6. // 1. Redistributions of source code must retain the above copyright notice,
  7. // this list of conditions and the following disclaimer.
  8. //
  9. // 2. Redistributions in binary form must reproduce the above copyright notice,
  10. // this list of conditions and the following disclaimer in the documentation
  11. // and/or other materials provided with the distribution.
  12. //
  13. // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  14. // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  15. // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  16. // APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  17. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
  18. // DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  19. // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20. // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. #include <log4cplus/config.hxx>
  24. #ifndef LOG4CPLUS_SINGLE_THREADED
  25. #include <log4cplus/helpers/queue.h>
  26. #include <log4cplus/helpers/loglog.h>
  27. #include <log4cplus/thread/syncprims-pub-impl.h>
  28. #include <stdexcept>
  29. #include <algorithm>
  30. #include <iterator>
  31. namespace log4cplus { namespace thread {
  32. Queue::Queue (unsigned len)
  33. : mutex (Mutex::DEFAULT)
  34. , ev_consumer (false)
  35. , sem (len, len)
  36. , flags (DRAIN)
  37. { }
  38. Queue::~Queue ()
  39. { }
  40. Queue::flags_type
  41. Queue::put_event (spi::InternalLoggingEvent const & ev)
  42. {
  43. flags_type ret_flags = ERROR_BIT;
  44. try
  45. {
  46. ev.gatherThreadSpecificData ();
  47. SemaphoreGuard semguard (sem);
  48. MutexGuard mguard (mutex);
  49. ret_flags |= flags;
  50. if (flags & EXIT)
  51. {
  52. ret_flags &= ~(ERROR_BIT | ERROR_AFTER);
  53. return ret_flags;
  54. }
  55. else
  56. {
  57. queue.push_back (ev);
  58. ret_flags |= ERROR_AFTER;
  59. semguard.detach ();
  60. flags |= QUEUE;
  61. ret_flags |= flags;
  62. mguard.unlock ();
  63. mguard.detach ();
  64. ev_consumer.signal ();
  65. }
  66. }
  67. catch (std::runtime_error const & e)
  68. {
  69. (void)e;
  70. return ret_flags;
  71. }
  72. ret_flags &= ~(ERROR_BIT | ERROR_AFTER);
  73. return ret_flags;
  74. }
  75. Queue::flags_type
  76. Queue::signal_exit (bool drain)
  77. {
  78. flags_type ret_flags = 0;
  79. try
  80. {
  81. MutexGuard mguard (mutex);
  82. ret_flags |= flags;
  83. if (! (flags & EXIT))
  84. {
  85. if (drain)
  86. flags |= DRAIN;
  87. else
  88. flags &= ~DRAIN;
  89. flags |= EXIT;
  90. ret_flags = flags;
  91. mguard.unlock ();
  92. mguard.detach ();
  93. ev_consumer.signal ();
  94. }
  95. }
  96. catch (std::runtime_error const & e)
  97. {
  98. (void)e;
  99. ret_flags |= ERROR_BIT;
  100. return ret_flags;
  101. }
  102. return ret_flags;
  103. }
  104. Queue::flags_type
  105. Queue::get_events (queue_storage_type * buf)
  106. {
  107. flags_type ret_flags = 0;
  108. try
  109. {
  110. while (true)
  111. {
  112. MutexGuard mguard (mutex);
  113. ret_flags = flags;
  114. if (((QUEUE & flags) && ! (EXIT & flags))
  115. || ((EXIT | DRAIN | QUEUE) & flags) == (EXIT | DRAIN | QUEUE))
  116. {
  117. assert (! queue.empty ());
  118. std::size_t const count = queue.size ();
  119. queue.swap (*buf);
  120. queue.clear ();
  121. flags &= ~QUEUE;
  122. for (std::size_t i = 0; i != count; ++i)
  123. sem.unlock ();
  124. ret_flags = flags | EVENT;
  125. break;
  126. }
  127. else if (((EXIT | QUEUE) & flags) == (EXIT | QUEUE))
  128. {
  129. assert (! queue.empty ());
  130. queue.clear ();
  131. flags &= ~QUEUE;
  132. ev_consumer.reset ();
  133. sem.unlock ();
  134. ret_flags = flags;
  135. break;
  136. }
  137. else if (EXIT & flags)
  138. break;
  139. else
  140. {
  141. ev_consumer.reset ();
  142. mguard.unlock ();
  143. mguard.detach ();
  144. ev_consumer.wait ();
  145. }
  146. }
  147. }
  148. catch (std::runtime_error const & e)
  149. {
  150. (void)e;
  151. ret_flags |= ERROR_BIT;
  152. }
  153. return ret_flags;
  154. }
  155. } } // namespace log4cplus { namespace thread {
  156. #endif // LOG4CPLUS_SINGLE_THREADED