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 template<typename DataType
>
48 class MessageQueue
: Noncopyable
{
50 MessageQueue() : m_killed(false) { }
52 void append(const DataType
&);
53 bool appendAndCheckEmpty(const DataType
&);
54 void prepend(const DataType
&);
55 bool waitForMessage(DataType
&);
56 template<typename Predicate
>
57 MessageQueueWaitResult
waitForMessageFilteredWithTimeout(DataType
&, Predicate
&, double absoluteTime
);
60 bool tryGetMessage(DataType
&);
63 // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
66 static double infiniteTime() { return std::numeric_limits
<double>::max(); }
69 static bool alwaysTruePredicate(DataType
&) { return true; }
71 mutable Mutex m_mutex
;
72 ThreadCondition m_condition
;
73 Deque
<DataType
> m_queue
;
77 template<typename DataType
>
78 inline void MessageQueue
<DataType
>::append(const DataType
& message
)
80 MutexLocker
lock(m_mutex
);
81 m_queue
.append(message
);
85 // Returns true if the queue was empty before the item was added.
86 template<typename DataType
>
87 inline bool MessageQueue
<DataType
>::appendAndCheckEmpty(const DataType
& message
)
89 MutexLocker
lock(m_mutex
);
90 bool wasEmpty
= m_queue
.isEmpty();
91 m_queue
.append(message
);
96 template<typename DataType
>
97 inline void MessageQueue
<DataType
>::prepend(const DataType
& message
)
99 MutexLocker
lock(m_mutex
);
100 m_queue
.prepend(message
);
101 m_condition
.signal();
104 template<typename DataType
>
105 inline bool MessageQueue
<DataType
>::waitForMessage(DataType
& result
)
107 MessageQueueWaitResult exitReason
= waitForMessageFilteredWithTimeout(result
, MessageQueue
<DataType
>::alwaysTruePredicate
, infiniteTime());
108 ASSERT(exitReason
== MessageQueueTerminated
|| exitReason
== MessageQueueMessageReceived
);
109 return exitReason
== MessageQueueMessageReceived
;
112 template<typename DataType
>
113 template<typename Predicate
>
114 inline MessageQueueWaitResult MessageQueue
<DataType
>::waitForMessageFilteredWithTimeout(DataType
& result
, Predicate
& predicate
, double absoluteTime
)
116 MutexLocker
lock(m_mutex
);
117 bool timedOut
= false;
119 DequeConstIterator
<DataType
> found
= m_queue
.end();
120 while (!m_killed
&& !timedOut
&& (found
= m_queue
.findIf(predicate
)) == m_queue
.end())
121 timedOut
= !m_condition
.timedWait(m_mutex
, absoluteTime
);
123 ASSERT(!timedOut
|| absoluteTime
!= infiniteTime());
126 return MessageQueueTerminated
;
129 return MessageQueueTimeout
;
131 ASSERT(found
!= m_queue
.end());
133 m_queue
.remove(found
);
134 return MessageQueueMessageReceived
;
137 template<typename DataType
>
138 inline bool MessageQueue
<DataType
>::tryGetMessage(DataType
& result
)
140 MutexLocker
lock(m_mutex
);
143 if (m_queue
.isEmpty())
146 result
= m_queue
.first();
147 m_queue
.removeFirst();
151 template<typename DataType
>
152 inline bool MessageQueue
<DataType
>::isEmpty()
154 MutexLocker
lock(m_mutex
);
157 return m_queue
.isEmpty();
160 template<typename DataType
>
161 inline void MessageQueue
<DataType
>::kill()
163 MutexLocker
lock(m_mutex
);
165 m_condition
.broadcast();
168 template<typename DataType
>
169 inline bool MessageQueue
<DataType
>::killed() const
171 MutexLocker
lock(m_mutex
);
176 using WTF::MessageQueue
;
177 // MessageQueueWaitResult enum and all its values.
178 using WTF::MessageQueueWaitResult
;
179 using WTF::MessageQueueTerminated
;
180 using WTF::MessageQueueTimeout
;
181 using WTF::MessageQueueMessageReceived
;
183 #endif // MessageQueue_h