]> git.saurik.com Git - apple/javascriptcore.git/blame - wtf/ThreadingQt.cpp
JavaScriptCore-521.tar.gz
[apple/javascriptcore.git] / wtf / ThreadingQt.cpp
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
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#include "config.h"
30#include "Threading.h"
31
32#include "CurrentTime.h"
33#include "HashMap.h"
34#include "MainThread.h"
35#include "RandomNumberSeed.h"
36
37#include <QCoreApplication>
38#include <QMutex>
39#include <QThread>
40#include <QWaitCondition>
41
42namespace WTF {
43
44class ThreadPrivate : public QThread {
45public:
46 ThreadPrivate(ThreadFunction entryPoint, void* data);
47 void run();
48 void* getReturnValue() { return m_returnValue; }
49private:
50 void* m_data;
51 ThreadFunction m_entryPoint;
52 void* m_returnValue;
53};
54
55ThreadPrivate::ThreadPrivate(ThreadFunction entryPoint, void* data)
56 : m_data(data)
57 , m_entryPoint(entryPoint)
58 , m_returnValue(0)
59{
60}
61
62void ThreadPrivate::run()
63{
64 m_returnValue = m_entryPoint(m_data);
65}
66
67
68static Mutex* atomicallyInitializedStaticMutex;
69
70static ThreadIdentifier mainThreadIdentifier;
71
72static Mutex& threadMapMutex()
73{
74 static Mutex mutex;
75 return mutex;
76}
77
78static HashMap<ThreadIdentifier, QThread*>& threadMap()
79{
80 static HashMap<ThreadIdentifier, QThread*> map;
81 return map;
82}
83
84static ThreadIdentifier identifierByQthreadHandle(QThread*& thread)
85{
86 MutexLocker locker(threadMapMutex());
87
88 HashMap<ThreadIdentifier, QThread*>::iterator i = threadMap().begin();
89 for (; i != threadMap().end(); ++i) {
90 if (i->second == thread)
91 return i->first;
92 }
93
94 return 0;
95}
96
97static ThreadIdentifier establishIdentifierForThread(QThread*& thread)
98{
99 ASSERT(!identifierByQthreadHandle(thread));
100
101 MutexLocker locker(threadMapMutex());
102
103 static ThreadIdentifier identifierCount = 1;
104
105 threadMap().add(identifierCount, thread);
106
107 return identifierCount++;
108}
109
110static void clearThreadForIdentifier(ThreadIdentifier id)
111{
112 MutexLocker locker(threadMapMutex());
113
114 ASSERT(threadMap().contains(id));
115
116 threadMap().remove(id);
117}
118
119static QThread* threadForIdentifier(ThreadIdentifier id)
120{
121 MutexLocker locker(threadMapMutex());
122
123 return threadMap().get(id);
124}
125
126void initializeThreading()
127{
128 if (!atomicallyInitializedStaticMutex) {
129 atomicallyInitializedStaticMutex = new Mutex;
130 threadMapMutex();
131 initializeRandomNumberGenerator();
132 QThread* mainThread = QCoreApplication::instance()->thread();
133 mainThreadIdentifier = identifierByQthreadHandle(mainThread);
134 if (!mainThreadIdentifier)
135 mainThreadIdentifier = establishIdentifierForThread(mainThread);
136 initializeMainThread();
137 }
138}
139
140void lockAtomicallyInitializedStaticMutex()
141{
142 ASSERT(atomicallyInitializedStaticMutex);
143 atomicallyInitializedStaticMutex->lock();
144}
145
146void unlockAtomicallyInitializedStaticMutex()
147{
148 atomicallyInitializedStaticMutex->unlock();
149}
150
151ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
152{
153 ThreadPrivate* thread = new ThreadPrivate(entryPoint, data);
154 if (!thread) {
155 LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
156 return 0;
157 }
158 thread->start();
159
160 QThread* threadRef = static_cast<QThread*>(thread);
161
162 return establishIdentifierForThread(threadRef);
163}
164
165int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
166{
167 ASSERT(threadID);
168
169 QThread* thread = threadForIdentifier(threadID);
170
171 bool res = thread->wait();
172
173 clearThreadForIdentifier(threadID);
174 if (result)
175 *result = static_cast<ThreadPrivate*>(thread)->getReturnValue();
176
177 return !res;
178}
179
180void detachThread(ThreadIdentifier)
181{
182}
183
184ThreadIdentifier currentThread()
185{
186 QThread* currentThread = QThread::currentThread();
187 if (ThreadIdentifier id = identifierByQthreadHandle(currentThread))
188 return id;
189 return establishIdentifierForThread(currentThread);
190}
191
192bool isMainThread()
193{
194 return currentThread() == mainThreadIdentifier;
195}
196
197Mutex::Mutex()
198 : m_mutex(new QMutex())
199{
200}
201
202Mutex::~Mutex()
203{
204 delete m_mutex;
205}
206
207void Mutex::lock()
208{
209 m_mutex->lock();
210}
211
212bool Mutex::tryLock()
213{
214 return m_mutex->tryLock();
215}
216
217void Mutex::unlock()
218{
219 m_mutex->unlock();
220}
221
222ThreadCondition::ThreadCondition()
223 : m_condition(new QWaitCondition())
224{
225}
226
227ThreadCondition::~ThreadCondition()
228{
229 delete m_condition;
230}
231
232void ThreadCondition::wait(Mutex& mutex)
233{
234 m_condition->wait(mutex.impl());
235}
236
237bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
238{
239 double currentTime = WTF::currentTime();
240
241 // Time is in the past - return immediately.
242 if (absoluteTime < currentTime)
243 return false;
244
245 double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
246 // Qt defines wait for up to ULONG_MAX milliseconds.
247 if (intervalMilliseconds >= ULONG_MAX)
248 intervalMilliseconds = ULONG_MAX;
249
250 return m_condition->wait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
251}
252
253void ThreadCondition::signal()
254{
255 m_condition->wakeOne();
256}
257
258void ThreadCondition::broadcast()
259{
260 m_condition->wakeAll();
261}
262
263} // namespace WebCore