• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MessageQueue()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>
append(const DataType & message)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>
prepend(const DataType & message)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>
waitForMessage(DataType & result)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>
waitForMessageTimed(DataType & result,double absoluteTime)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>
tryGetMessage(DataType & result)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>
isEmpty()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>
kill()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>
killed()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
170