MessageQueue.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * Copyright (C) 2008 Apple Inc. All rights reserved.
  3. * Copyright (C) 2009 Google Inc. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  15. * its contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  19. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #ifndef MessageQueue_h
  30. #define MessageQueue_h
  31. #include <limits>
  32. #include <wtf/Assertions.h>
  33. #include <wtf/Deque.h>
  34. #include <wtf/Noncopyable.h>
  35. #include <wtf/Threading.h>
  36. namespace WTF {
  37. enum MessageQueueWaitResult {
  38. MessageQueueTerminated, // Queue was destroyed while waiting for message.
  39. MessageQueueTimeout, // Timeout was specified and it expired.
  40. MessageQueueMessageReceived // A message was successfully received and returned.
  41. };
  42. // The queue takes ownership of messages and transfer it to the new owner
  43. // when messages are fetched from the queue.
  44. // Essentially, MessageQueue acts as a queue of OwnPtr<DataType>.
  45. template<typename DataType>
  46. class MessageQueue {
  47. WTF_MAKE_NONCOPYABLE(MessageQueue);
  48. public:
  49. #if USE(MANX_COND_INIT)
  50. MessageQueue() : m_condition(m_mutex) , m_killed(false) { }
  51. #else
  52. MessageQueue() : m_killed(false) { }
  53. #endif
  54. ~MessageQueue();
  55. void append(PassOwnPtr<DataType>);
  56. void appendAndKill(PassOwnPtr<DataType>);
  57. bool appendAndCheckEmpty(PassOwnPtr<DataType>);
  58. void prepend(PassOwnPtr<DataType>);
  59. PassOwnPtr<DataType> waitForMessage();
  60. PassOwnPtr<DataType> tryGetMessage();
  61. PassOwnPtr<DataType> tryGetMessageIgnoringKilled();
  62. template<typename Predicate>
  63. PassOwnPtr<DataType> waitForMessageFilteredWithTimeout(MessageQueueWaitResult&, Predicate&, double absoluteTime);
  64. template<typename Predicate>
  65. void removeIf(Predicate&);
  66. void kill();
  67. bool killed() const;
  68. // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
  69. bool isEmpty();
  70. static double infiniteTime() { return std::numeric_limits<double>::max(); }
  71. private:
  72. static bool alwaysTruePredicate(DataType*) { return true; }
  73. mutable Mutex m_mutex;
  74. ThreadCondition m_condition;
  75. Deque<DataType*> m_queue;
  76. bool m_killed;
  77. };
  78. template<typename DataType>
  79. MessageQueue<DataType>::~MessageQueue()
  80. {
  81. deleteAllValues(m_queue);
  82. }
  83. template<typename DataType>
  84. inline void MessageQueue<DataType>::append(PassOwnPtr<DataType> message)
  85. {
  86. MutexLocker lock(m_mutex);
  87. m_queue.append(message.leakPtr());
  88. m_condition.signal();
  89. }
  90. template<typename DataType>
  91. inline void MessageQueue<DataType>::appendAndKill(PassOwnPtr<DataType> message)
  92. {
  93. MutexLocker lock(m_mutex);
  94. m_queue.append(message.leakPtr());
  95. m_killed = true;
  96. m_condition.broadcast();
  97. }
  98. // Returns true if the queue was empty before the item was added.
  99. template<typename DataType>
  100. inline bool MessageQueue<DataType>::appendAndCheckEmpty(PassOwnPtr<DataType> message)
  101. {
  102. MutexLocker lock(m_mutex);
  103. bool wasEmpty = m_queue.isEmpty();
  104. m_queue.append(message.leakPtr());
  105. m_condition.signal();
  106. return wasEmpty;
  107. }
  108. template<typename DataType>
  109. inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message)
  110. {
  111. MutexLocker lock(m_mutex);
  112. m_queue.prepend(message.leakPtr());
  113. m_condition.signal();
  114. }
  115. template<typename DataType>
  116. inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessage()
  117. {
  118. MessageQueueWaitResult exitReason;
  119. OwnPtr<DataType> result = waitForMessageFilteredWithTimeout(exitReason, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
  120. ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
  121. return result.release();
  122. }
  123. template<typename DataType>
  124. template<typename Predicate>
  125. inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessageFilteredWithTimeout(MessageQueueWaitResult& result, Predicate& predicate, double absoluteTime)
  126. {
  127. MutexLocker lock(m_mutex);
  128. bool timedOut = false;
  129. DequeConstIterator<DataType*> found = m_queue.end();
  130. while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end())
  131. timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
  132. ASSERT(!timedOut || absoluteTime != infiniteTime());
  133. if (m_killed) {
  134. result = MessageQueueTerminated;
  135. return nullptr;
  136. }
  137. if (timedOut) {
  138. result = MessageQueueTimeout;
  139. return nullptr;
  140. }
  141. ASSERT(found != m_queue.end());
  142. OwnPtr<DataType> message = adoptPtr(*found);
  143. m_queue.remove(found);
  144. result = MessageQueueMessageReceived;
  145. return message.release();
  146. }
  147. template<typename DataType>
  148. inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessage()
  149. {
  150. MutexLocker lock(m_mutex);
  151. if (m_killed)
  152. return nullptr;
  153. if (m_queue.isEmpty())
  154. return nullptr;
  155. return adoptPtr(m_queue.takeFirst());
  156. }
  157. template<typename DataType>
  158. inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessageIgnoringKilled()
  159. {
  160. MutexLocker lock(m_mutex);
  161. if (m_queue.isEmpty())
  162. return nullptr;
  163. return adoptPtr(m_queue.takeFirst());
  164. }
  165. template<typename DataType>
  166. template<typename Predicate>
  167. inline void MessageQueue<DataType>::removeIf(Predicate& predicate)
  168. {
  169. MutexLocker lock(m_mutex);
  170. DequeConstIterator<DataType*> found = m_queue.end();
  171. while ((found = m_queue.findIf(predicate)) != m_queue.end()) {
  172. DataType* message = *found;
  173. m_queue.remove(found);
  174. delete message;
  175. }
  176. }
  177. template<typename DataType>
  178. inline bool MessageQueue<DataType>::isEmpty()
  179. {
  180. MutexLocker lock(m_mutex);
  181. if (m_killed)
  182. return true;
  183. return m_queue.isEmpty();
  184. }
  185. template<typename DataType>
  186. inline void MessageQueue<DataType>::kill()
  187. {
  188. MutexLocker lock(m_mutex);
  189. m_killed = true;
  190. m_condition.broadcast();
  191. }
  192. template<typename DataType>
  193. inline bool MessageQueue<DataType>::killed() const
  194. {
  195. MutexLocker lock(m_mutex);
  196. return m_killed;
  197. }
  198. } // namespace WTF
  199. using WTF::MessageQueue;
  200. // MessageQueueWaitResult enum and all its values.
  201. using WTF::MessageQueueWaitResult;
  202. using WTF::MessageQueueTerminated;
  203. using WTF::MessageQueueTimeout;
  204. using WTF::MessageQueueMessageReceived;
  205. #endif // MessageQueue_h