2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
30 #ifndef MessageQueue_h
31 #define MessageQueue_h
34 #include <wtf/Assertions.h>
35 #include <wtf/Deque.h>
36 #include <wtf/Noncopyable.h>
37 #include <wtf/Threading.h>
41 enum MessageQueueWaitResult
{
42 MessageQueueTerminated
, // Queue was destroyed while waiting for message.
43 MessageQueueTimeout
, // Timeout was specified and it expired.
44 MessageQueueMessageReceived
, // A message was successfully received and returned.
47 // The queue takes ownership of messages and transfer it to the new owner
48 // when messages are fetched from the queue.
49 // Essentially, MessageQueue acts as a queue of OwnPtr<DataType>.
50 template<typename DataType
>
51 class MessageQueue
: public Noncopyable
{
53 MessageQueue() : m_killed(false) { }
56 void append(PassOwnPtr
<DataType
>);
57 bool appendAndCheckEmpty(PassOwnPtr
<DataType
>);
58 void prepend(PassOwnPtr
<DataType
>);
60 PassOwnPtr
<DataType
> waitForMessage();
61 PassOwnPtr
<DataType
> tryGetMessage();
62 template<typename Predicate
>
63 PassOwnPtr
<DataType
> waitForMessageFilteredWithTimeout(MessageQueueWaitResult
&, Predicate
&, double absoluteTime
);
65 template<typename Predicate
>
66 void removeIf(Predicate
&);
71 // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
74 static double infiniteTime() { return std::numeric_limits
<double>::max(); }
77 static bool alwaysTruePredicate(DataType
*) { return true; }
79 mutable Mutex m_mutex
;
80 ThreadCondition m_condition
;
81 Deque
<DataType
*> m_queue
;
85 template<typename DataType
>
86 MessageQueue
<DataType
>::~MessageQueue()
88 deleteAllValues(m_queue
);
91 template<typename DataType
>
92 inline void MessageQueue
<DataType
>::append(PassOwnPtr
<DataType
> message
)
94 MutexLocker
lock(m_mutex
);
95 m_queue
.append(message
.release());
99 // Returns true if the queue was empty before the item was added.
100 template<typename DataType
>
101 inline bool MessageQueue
<DataType
>::appendAndCheckEmpty(PassOwnPtr
<DataType
> message
)
103 MutexLocker
lock(m_mutex
);
104 bool wasEmpty
= m_queue
.isEmpty();
105 m_queue
.append(message
.release());
106 m_condition
.signal();
110 template<typename DataType
>
111 inline void MessageQueue
<DataType
>::prepend(PassOwnPtr
<DataType
> message
)
113 MutexLocker
lock(m_mutex
);
114 m_queue
.prepend(message
.release());
115 m_condition
.signal();
118 template<typename DataType
>
119 inline PassOwnPtr
<DataType
> MessageQueue
<DataType
>::waitForMessage()
121 MessageQueueWaitResult exitReason
;
122 PassOwnPtr
<DataType
> result
= waitForMessageFilteredWithTimeout(exitReason
, MessageQueue
<DataType
>::alwaysTruePredicate
, infiniteTime());
123 ASSERT(exitReason
== MessageQueueTerminated
|| exitReason
== MessageQueueMessageReceived
);
127 template<typename DataType
>
128 template<typename Predicate
>
129 inline PassOwnPtr
<DataType
> MessageQueue
<DataType
>::waitForMessageFilteredWithTimeout(MessageQueueWaitResult
& result
, Predicate
& predicate
, double absoluteTime
)
131 MutexLocker
lock(m_mutex
);
132 bool timedOut
= false;
134 DequeConstIterator
<DataType
*> found
= m_queue
.end();
135 while (!m_killed
&& !timedOut
&& (found
= m_queue
.findIf(predicate
)) == m_queue
.end())
136 timedOut
= !m_condition
.timedWait(m_mutex
, absoluteTime
);
138 ASSERT(!timedOut
|| absoluteTime
!= infiniteTime());
141 result
= MessageQueueTerminated
;
146 result
= MessageQueueTimeout
;
150 ASSERT(found
!= m_queue
.end());
151 DataType
* message
= *found
;
152 m_queue
.remove(found
);
153 result
= MessageQueueMessageReceived
;
157 template<typename DataType
>
158 inline PassOwnPtr
<DataType
> MessageQueue
<DataType
>::tryGetMessage()
160 MutexLocker
lock(m_mutex
);
163 if (m_queue
.isEmpty())
166 DataType
* message
= m_queue
.first();
167 m_queue
.removeFirst();
171 template<typename DataType
>
172 template<typename Predicate
>
173 inline void MessageQueue
<DataType
>::removeIf(Predicate
& predicate
)
175 MutexLocker
lock(m_mutex
);
176 // See bug 31657 for why this loop looks so weird
178 DequeConstIterator
<DataType
*> found
= m_queue
.findIf(predicate
);
179 if (found
== m_queue
.end())
182 DataType
* message
= *found
;
183 m_queue
.remove(found
);
188 template<typename DataType
>
189 inline bool MessageQueue
<DataType
>::isEmpty()
191 MutexLocker
lock(m_mutex
);
194 return m_queue
.isEmpty();
197 template<typename DataType
>
198 inline void MessageQueue
<DataType
>::kill()
200 MutexLocker
lock(m_mutex
);
202 m_condition
.broadcast();
205 template<typename DataType
>
206 inline bool MessageQueue
<DataType
>::killed() const
208 MutexLocker
lock(m_mutex
);
213 using WTF::MessageQueue
;
214 // MessageQueueWaitResult enum and all its values.
215 using WTF::MessageQueueWaitResult
;
216 using WTF::MessageQueueTerminated
;
217 using WTF::MessageQueueTimeout
;
218 using WTF::MessageQueueMessageReceived
;
220 #endif // MessageQueue_h