2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
30 #include "Threading.h"
32 #if !ENABLE(SINGLE_THREADED)
34 #include "CurrentTime.h"
36 #include "MainThread.h"
37 #include "RandomNumberSeed.h"
39 #include <QCoreApplication>
42 #include <QWaitCondition>
46 class ThreadPrivate
: public QThread
{
48 ThreadPrivate(ThreadFunction entryPoint
, void* data
);
50 void* getReturnValue() { return m_returnValue
; }
53 ThreadFunction m_entryPoint
;
57 ThreadPrivate::ThreadPrivate(ThreadFunction entryPoint
, void* data
)
59 , m_entryPoint(entryPoint
)
64 void ThreadPrivate::run()
66 m_returnValue
= m_entryPoint(m_data
);
69 class ThreadMonitor
: public QObject
{
72 static ThreadMonitor
* instance()
74 static ThreadMonitor
*instance
= new ThreadMonitor();
81 sender()->deleteLater();
85 static Mutex
* atomicallyInitializedStaticMutex
;
87 static Mutex
& threadMapMutex()
93 static HashMap
<ThreadIdentifier
, QThread
*>& threadMap()
95 static HashMap
<ThreadIdentifier
, QThread
*> map
;
99 static ThreadIdentifier
identifierByQthreadHandle(QThread
*& thread
)
101 MutexLocker
locker(threadMapMutex());
103 HashMap
<ThreadIdentifier
, QThread
*>::iterator i
= threadMap().begin();
104 for (; i
!= threadMap().end(); ++i
) {
105 if (i
->second
== thread
)
112 static ThreadIdentifier
establishIdentifierForThread(QThread
*& thread
)
114 ASSERT(!identifierByQthreadHandle(thread
));
116 MutexLocker
locker(threadMapMutex());
118 static ThreadIdentifier identifierCount
= 1;
120 threadMap().add(identifierCount
, thread
);
122 return identifierCount
++;
125 static void clearThreadForIdentifier(ThreadIdentifier id
)
127 MutexLocker
locker(threadMapMutex());
129 ASSERT(threadMap().contains(id
));
131 threadMap().remove(id
);
134 static QThread
* threadForIdentifier(ThreadIdentifier id
)
136 MutexLocker
locker(threadMapMutex());
138 return threadMap().get(id
);
141 void initializeThreading()
143 if (!atomicallyInitializedStaticMutex
) {
144 atomicallyInitializedStaticMutex
= new Mutex
;
146 initializeRandomNumberGenerator();
150 void lockAtomicallyInitializedStaticMutex()
152 ASSERT(atomicallyInitializedStaticMutex
);
153 atomicallyInitializedStaticMutex
->lock();
156 void unlockAtomicallyInitializedStaticMutex()
158 atomicallyInitializedStaticMutex
->unlock();
161 ThreadIdentifier
createThreadInternal(ThreadFunction entryPoint
, void* data
, const char*)
163 ThreadPrivate
* thread
= new ThreadPrivate(entryPoint
, data
);
165 LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint
, data
);
169 QObject::connect(thread
, SIGNAL(finished()), ThreadMonitor::instance(), SLOT(threadFinished()));
173 QThread
* threadRef
= static_cast<QThread
*>(thread
);
175 return establishIdentifierForThread(threadRef
);
178 void initializeCurrentThreadInternal(const char*)
182 int waitForThreadCompletion(ThreadIdentifier threadID
, void** result
)
186 QThread
* thread
= threadForIdentifier(threadID
);
188 bool res
= thread
->wait();
190 clearThreadForIdentifier(threadID
);
192 *result
= static_cast<ThreadPrivate
*>(thread
)->getReturnValue();
197 void detachThread(ThreadIdentifier threadID
)
200 clearThreadForIdentifier(threadID
);
203 ThreadIdentifier
currentThread()
205 QThread
* currentThread
= QThread::currentThread();
206 if (ThreadIdentifier id
= identifierByQthreadHandle(currentThread
))
208 return establishIdentifierForThread(currentThread
);
212 : m_mutex(new QMutex())
226 bool Mutex::tryLock()
228 return m_mutex
->tryLock();
236 ThreadCondition::ThreadCondition()
237 : m_condition(new QWaitCondition())
241 ThreadCondition::~ThreadCondition()
246 void ThreadCondition::wait(Mutex
& mutex
)
248 m_condition
->wait(mutex
.impl());
251 bool ThreadCondition::timedWait(Mutex
& mutex
, double absoluteTime
)
253 double currentTime
= WTF::currentTime();
255 // Time is in the past - return immediately.
256 if (absoluteTime
< currentTime
)
259 // Time is too far in the future (and would overflow unsigned long) - wait forever.
260 if (absoluteTime
- currentTime
> static_cast<double>(INT_MAX
) / 1000.0) {
265 double intervalMilliseconds
= (absoluteTime
- currentTime
) * 1000.0;
266 return m_condition
->wait(mutex
.impl(), static_cast<unsigned long>(intervalMilliseconds
));
269 void ThreadCondition::signal()
271 m_condition
->wakeOne();
274 void ThreadCondition::broadcast()
276 m_condition
->wakeAll();
279 } // namespace WebCore
281 #include "ThreadingQt.moc"