Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / wtf / MessageQueue.h
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
30 #ifndef MessageQueue_h
31 #define MessageQueue_h
32
33 #include <limits>
34 #include "wtf/Assertions.h"
35 #include "wtf/Deque.h"
36 #include "wtf/Noncopyable.h"
37 #include "wtf/OwnPtr.h"
38 #include "wtf/PassOwnPtr.h"
39 #include "wtf/ThreadingPrimitives.h"
40
41 namespace WTF {
42
43     enum MessageQueueWaitResult {
44         MessageQueueTerminated,       // Queue was destroyed while waiting for message.
45         MessageQueueTimeout,          // Timeout was specified and it expired.
46         MessageQueueMessageReceived   // A message was successfully received and returned.
47     };
48
49     // The queue takes ownership of messages and transfer it to the new owner
50     // when messages are fetched from the queue.
51     // Essentially, MessageQueue acts as a queue of OwnPtr<DataType>.
52     template<typename DataType>
53     class MessageQueue {
54         WTF_MAKE_NONCOPYABLE(MessageQueue);
55     public:
56         MessageQueue() : m_killed(false) { }
57
58         // Returns true if the queue is still alive, false if the queue has been killed.
59         bool append(PassOwnPtr<DataType>);
60         void appendAndKill(PassOwnPtr<DataType>);
61         bool appendAndCheckEmpty(PassOwnPtr<DataType>);
62         void prepend(PassOwnPtr<DataType>);
63
64         PassOwnPtr<DataType> waitForMessage();
65         PassOwnPtr<DataType> tryGetMessage();
66         PassOwnPtr<DataType> tryGetMessageIgnoringKilled();
67         PassOwnPtr<DataType> waitForMessageWithTimeout(MessageQueueWaitResult&, double absoluteTime);
68
69         void kill();
70         bool killed() const;
71
72         // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
73         bool isEmpty();
74
75         static double infiniteTime() { return std::numeric_limits<double>::max(); }
76
77     private:
78         mutable Mutex m_mutex;
79         ThreadCondition m_condition;
80         Deque<OwnPtr<DataType> > m_queue;
81         bool m_killed;
82     };
83
84     template<typename DataType>
85     inline bool MessageQueue<DataType>::append(PassOwnPtr<DataType> message)
86     {
87         MutexLocker lock(m_mutex);
88         m_queue.append(message);
89         m_condition.signal();
90         return !m_killed;
91     }
92
93     template<typename DataType>
94     inline void MessageQueue<DataType>::appendAndKill(PassOwnPtr<DataType> message)
95     {
96         MutexLocker lock(m_mutex);
97         m_queue.append(message);
98         m_killed = true;
99         m_condition.broadcast();
100     }
101
102     // Returns true if the queue was empty before the item was added.
103     template<typename DataType>
104     inline bool MessageQueue<DataType>::appendAndCheckEmpty(PassOwnPtr<DataType> message)
105     {
106         MutexLocker lock(m_mutex);
107         bool wasEmpty = m_queue.isEmpty();
108         m_queue.append(message);
109         m_condition.signal();
110         return wasEmpty;
111     }
112
113     template<typename DataType>
114     inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message)
115     {
116         MutexLocker lock(m_mutex);
117         m_queue.prepend(message);
118         m_condition.signal();
119     }
120
121     template<typename DataType>
122     inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessage()
123     {
124         MessageQueueWaitResult exitReason;
125         OwnPtr<DataType> result = waitForMessageWithTimeout(exitReason, infiniteTime());
126         ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
127         return result.release();
128     }
129
130     template<typename DataType>
131     inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessageWithTimeout(MessageQueueWaitResult& result, double absoluteTime)
132     {
133         MutexLocker lock(m_mutex);
134         bool timedOut = false;
135
136         while (!m_killed && !timedOut && m_queue.isEmpty())
137             timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
138
139         ASSERT(!timedOut || absoluteTime != infiniteTime());
140
141         if (m_killed) {
142             result = MessageQueueTerminated;
143             return nullptr;
144         }
145
146         if (timedOut) {
147             result = MessageQueueTimeout;
148             return nullptr;
149         }
150
151         ASSERT_WITH_SECURITY_IMPLICATION(!m_queue.isEmpty());
152         result = MessageQueueMessageReceived;
153
154         return m_queue.takeFirst();
155     }
156
157     template<typename DataType>
158     inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessage()
159     {
160         MutexLocker lock(m_mutex);
161         if (m_killed)
162             return nullptr;
163         if (m_queue.isEmpty())
164             return nullptr;
165
166         return m_queue.takeFirst();
167     }
168
169     template<typename DataType>
170     inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessageIgnoringKilled()
171     {
172         MutexLocker lock(m_mutex);
173         if (m_queue.isEmpty())
174             return nullptr;
175
176         return m_queue.takeFirst();
177     }
178
179     template<typename DataType>
180     inline bool MessageQueue<DataType>::isEmpty()
181     {
182         MutexLocker lock(m_mutex);
183         if (m_killed)
184             return true;
185         return m_queue.isEmpty();
186     }
187
188     template<typename DataType>
189     inline void MessageQueue<DataType>::kill()
190     {
191         MutexLocker lock(m_mutex);
192         m_killed = true;
193         m_condition.broadcast();
194     }
195
196     template<typename DataType>
197     inline bool MessageQueue<DataType>::killed() const
198     {
199         MutexLocker lock(m_mutex);
200         return m_killed;
201     }
202 } // namespace WTF
203
204 using WTF::MessageQueue;
205 // MessageQueueWaitResult enum and all its values.
206 using WTF::MessageQueueWaitResult;
207 using WTF::MessageQueueTerminated;
208 using WTF::MessageQueueTimeout;
209 using WTF::MessageQueueMessageReceived;
210
211 #endif // MessageQueue_h