Merge "Better solution for Docomo 1339 bug." into tizen_2.1
[framework/web/webkit-efl.git] / Source / WTF / 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/Threading.h>
38
39 namespace WTF {
40
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.
45     };
46
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 {
52         WTF_MAKE_NONCOPYABLE(MessageQueue);
53     public:
54         MessageQueue() : m_killed(false) { }
55         ~MessageQueue();
56
57         void append(PassOwnPtr<DataType>);
58         bool appendAndCheckEmpty(PassOwnPtr<DataType>);
59         void prepend(PassOwnPtr<DataType>);
60
61         PassOwnPtr<DataType> waitForMessage();
62         PassOwnPtr<DataType> tryGetMessage();
63         PassOwnPtr<DataType> tryGetMessageIgnoringKilled();
64         template<typename Predicate>
65         PassOwnPtr<DataType> waitForMessageFilteredWithTimeout(MessageQueueWaitResult&, Predicate&, double absoluteTime);
66
67         template<typename Predicate>
68         void removeIf(Predicate&);
69
70         void kill();
71         bool killed() const;
72
73         // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time.
74         bool isEmpty();
75
76         static double infiniteTime() { return std::numeric_limits<double>::max(); }
77
78     private:
79         static bool alwaysTruePredicate(DataType*) { return true; }
80
81         mutable Mutex m_mutex;
82         ThreadCondition m_condition;
83         Deque<DataType*> m_queue;
84         bool m_killed;
85     };
86
87     template<typename DataType>
88     MessageQueue<DataType>::~MessageQueue()
89     {
90         deleteAllValues(m_queue);
91     }
92
93     template<typename DataType>
94     inline void MessageQueue<DataType>::append(PassOwnPtr<DataType> message)
95     {
96         MutexLocker lock(m_mutex);
97         m_queue.append(message.leakPtr());
98         m_condition.signal();
99     }
100
101     // Returns true if the queue was empty before the item was added.
102     template<typename DataType>
103     inline bool MessageQueue<DataType>::appendAndCheckEmpty(PassOwnPtr<DataType> message)
104     {
105         MutexLocker lock(m_mutex);
106         bool wasEmpty = m_queue.isEmpty();
107         m_queue.append(message.leakPtr());
108         m_condition.signal();
109         return wasEmpty;
110     }
111
112     template<typename DataType>
113     inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message)
114     {
115         MutexLocker lock(m_mutex);
116         m_queue.prepend(message.leakPtr());
117         m_condition.signal();
118     }
119
120     template<typename DataType>
121     inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessage()
122     {
123         MessageQueueWaitResult exitReason; 
124         OwnPtr<DataType> result = waitForMessageFilteredWithTimeout(exitReason, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
125         ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
126         return result.release();
127     }
128
129     template<typename DataType>
130     template<typename Predicate>
131     inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessageFilteredWithTimeout(MessageQueueWaitResult& result, Predicate& predicate, double absoluteTime)
132     {
133         MutexLocker lock(m_mutex);
134         bool timedOut = false;
135
136         DequeConstIterator<DataType*> found = m_queue.end();
137         while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end())
138             timedOut = !m_condition.timedWait(m_mutex, absoluteTime);
139
140         ASSERT(!timedOut || absoluteTime != infiniteTime());
141
142         if (m_killed) {
143             result = MessageQueueTerminated;
144             return nullptr;
145         }
146
147         if (timedOut) {
148             result = MessageQueueTimeout;
149             return nullptr;
150         }
151
152         ASSERT(found != m_queue.end());
153         OwnPtr<DataType> message = adoptPtr(*found);
154         m_queue.remove(found);
155         result = MessageQueueMessageReceived;
156         return message.release();
157     }
158
159     template<typename DataType>
160     inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessage()
161     {
162         MutexLocker lock(m_mutex);
163         if (m_killed)
164             return nullptr;
165         if (m_queue.isEmpty())
166             return nullptr;
167
168         return adoptPtr(m_queue.takeFirst());
169     }
170
171     template<typename DataType>
172     inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessageIgnoringKilled()
173     {
174         MutexLocker lock(m_mutex);
175         if (m_queue.isEmpty())
176             return nullptr;
177
178         return adoptPtr(m_queue.takeFirst());
179     }
180
181     template<typename DataType>
182     template<typename Predicate>
183     inline void MessageQueue<DataType>::removeIf(Predicate& predicate)
184     {
185         MutexLocker lock(m_mutex);
186         DequeConstIterator<DataType*> found = m_queue.end();
187         while ((found = m_queue.findIf(predicate)) != m_queue.end()) {
188             DataType* message = *found;
189             m_queue.remove(found);
190             delete message;
191         }
192     }
193
194     template<typename DataType>
195     inline bool MessageQueue<DataType>::isEmpty()
196     {
197         MutexLocker lock(m_mutex);
198         if (m_killed)
199             return true;
200         return m_queue.isEmpty();
201     }
202
203     template<typename DataType>
204     inline void MessageQueue<DataType>::kill()
205     {
206         MutexLocker lock(m_mutex);
207         m_killed = true;
208         m_condition.broadcast();
209     }
210
211     template<typename DataType>
212     inline bool MessageQueue<DataType>::killed() const
213     {
214         MutexLocker lock(m_mutex);
215         return m_killed;
216     }
217 } // namespace WTF
218
219 using WTF::MessageQueue;
220 // MessageQueueWaitResult enum and all its values.
221 using WTF::MessageQueueWaitResult;
222 using WTF::MessageQueueTerminated;
223 using WTF::MessageQueueTimeout;
224 using WTF::MessageQueueMessageReceived;
225
226 #endif // MessageQueue_h