]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/MessageQueue.h
19c5c10fede9649a519bb480ba00b2212a0bc85f
[apple/javascriptcore.git] / wtf / MessageQueue.h
1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #ifndef MessageQueue_h
30 #define MessageQueue_h
31
32 #include <wtf/Assertions.h>
33 #include <wtf/Deque.h>
34 #include <wtf/Noncopyable.h>
35 #include <wtf/Threading.h>
36
37 namespace WTF {
38
39 enum MessageQueueWaitResult {
40 MessageQueueTerminated, // Queue was destroyed while waiting for message.
41 MessageQueueTimeout, // Timeout was specified and it expired.
42 MessageQueueMessageReceived, // A message was successfully received and returned.
43 };
44
45 template<typename DataType>
46 class MessageQueue : Noncopyable {
47 public:
48 MessageQueue() : m_killed(false) {}
49
50 void append(const DataType&);
51 void prepend(const DataType&);
52 bool waitForMessage(DataType&);
53 MessageQueueWaitResult waitForMessageTimed(DataType&, double absoluteTime);
54 void kill();
55
56 bool tryGetMessage(DataType&);
57 bool killed() const;
58
59 // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
60 bool isEmpty();
61
62 private:
63 mutable Mutex m_mutex;
64 ThreadCondition m_condition;
65 Deque<DataType> m_queue;
66 bool m_killed;
67 };
68
69 template<typename DataType>
70 inline void MessageQueue<DataType>::append(const DataType& message)
71 {
72 MutexLocker lock(m_mutex);
73 m_queue.append(message);
74 m_condition.signal();
75 }
76
77 template<typename DataType>
78 inline void MessageQueue<DataType>::prepend(const DataType& message)
79 {
80 MutexLocker lock(m_mutex);
81 m_queue.prepend(message);
82 m_condition.signal();
83 }
84
85 template<typename DataType>
86 inline bool MessageQueue<DataType>::waitForMessage(DataType& result)
87 {
88 MutexLocker lock(m_mutex);
89
90 while (!m_killed && m_queue.isEmpty())
91 m_condition.wait(m_mutex);
92
93 if (m_killed)
94 return false;
95
96 ASSERT(!m_queue.isEmpty());
97 result = m_queue.first();
98 m_queue.removeFirst();
99 return true;
100 }
101
102 template<typename DataType>
103 inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageTimed(DataType& result, double absoluteTime)
104 {
105 MutexLocker lock(m_mutex);
106 bool timedOut = false;
107
108 while (!m_killed && !timedOut && m_queue.isEmpty())
109 timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
110
111 if (m_killed)
112 return MessageQueueTerminated;
113
114 if (timedOut)
115 return MessageQueueTimeout;
116
117 ASSERT(!m_queue.isEmpty());
118 result = m_queue.first();
119 m_queue.removeFirst();
120 return MessageQueueMessageReceived;
121 }
122
123 template<typename DataType>
124 inline bool MessageQueue<DataType>::tryGetMessage(DataType& result)
125 {
126 MutexLocker lock(m_mutex);
127 if (m_killed)
128 return false;
129 if (m_queue.isEmpty())
130 return false;
131
132 result = m_queue.first();
133 m_queue.removeFirst();
134 return true;
135 }
136
137 template<typename DataType>
138 inline bool MessageQueue<DataType>::isEmpty()
139 {
140 MutexLocker lock(m_mutex);
141 if (m_killed)
142 return true;
143 return m_queue.isEmpty();
144 }
145
146 template<typename DataType>
147 inline void MessageQueue<DataType>::kill()
148 {
149 MutexLocker lock(m_mutex);
150 m_killed = true;
151 m_condition.broadcast();
152 }
153
154 template<typename DataType>
155 inline bool MessageQueue<DataType>::killed() const
156 {
157 MutexLocker lock(m_mutex);
158 return m_killed;
159 }
160 }
161
162 using WTF::MessageQueue;
163 // MessageQueueWaitResult enum and all its values.
164 using WTF::MessageQueueWaitResult;
165 using WTF::MessageQueueTerminated;
166 using WTF::MessageQueueTimeout;
167 using WTF::MessageQueueMessageReceived;
168
169 #endif // MessageQueue_h