source: webkit/trunk/JavaScriptCore/wtf/ThreadingQt.cpp@ 36124

Last change on this file since 36124 was 36056, checked in by [email protected], 17 years ago

Reviewed by Darin Adler.

Implement callOnMainThreadAndWait().

This will be useful when a background thread needs to perform UI calls synchronously
(e.g. an openDatabase() call cannot return until the user answers to a confirmation dialog).

  • wtf/MainThread.cpp: (WTF::FunctionWithContext::FunctionWithContext): Added a ThreadCondition member. When non-zero, the condition is signalled after the function is called. (WTF::mainThreadFunctionQueueMutex): Renamed from functionQueueMutex, sinc this is no longer static. Changed to be initialized from initializeThreading() to avoid lock contention. (WTF::initializeMainThread): On non-Windows platforms, just call mainThreadFunctionQueueMutex. (WTF::dispatchFunctionsFromMainThread): Signal synchronous calls when done. (WTF::callOnMainThread): Updated for functionQueueMutex rename. (WTF::callOnMainThreadAndWait): Added.
  • wtf/MainThread.h: Added callOnMainThreadAndWait(); initializeMainThread() now exists on all platforms.
  • wtf/win/MainThreadWin.cpp: (WTF::initializeMainThread): Added a callOnMainThreadAndWait() call to initialize function queue mutex.
  • wtf/ThreadingGtk.cpp: (WTF::initializeThreading):
  • wtf/ThreadingPthreads.cpp: (WTF::initializeThreading):
  • wtf/ThreadingQt.cpp: (WTF::initializeThreading): Only initialize mainThreadIdentifier on non-Darwin platforms. It was not guaranteed to be accurate on Darwin.
File size: 5.7 KB
Line 
1/*
2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Justin Haygood ([email protected])
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 "HashMap.h"
33#include "MainThread.h"
34#include "MathExtras.h"
35
36#include <QMutex>
37#include <QThread>
38#include <QWaitCondition>
39
40namespace WTF {
41
42class ThreadPrivate : public QThread {
43public:
44 ThreadPrivate(ThreadFunction entryPoint, void* data);
45 void run();
46 void* getReturnValue() { return m_returnValue; }
47private:
48 void* m_data;
49 ThreadFunction m_entryPoint;
50 void* m_returnValue;
51};
52
53ThreadPrivate::ThreadPrivate(ThreadFunction entryPoint, void* data)
54 : m_data(data)
55 , m_entryPoint(entryPoint)
56 , m_returnValue(0)
57{
58}
59
60void ThreadPrivate::run()
61{
62 m_returnValue = m_entryPoint(m_data);
63}
64
65
66Mutex* atomicallyInitializedStaticMutex;
67
68#if !PLATFORM(DARWIN)
69static ThreadIdentifier mainThreadIdentifier;
70#endif
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 establishIdentifierForThread(QThread*& thread)
85{
86 MutexLocker locker(threadMapMutex());
87
88 static ThreadIdentifier identifierCount = 1;
89
90 threadMap().add(identifierCount, thread);
91
92 return identifierCount++;
93}
94
95static void clearThreadForIdentifier(ThreadIdentifier id)
96{
97 MutexLocker locker(threadMapMutex());
98
99 ASSERT(threadMap().contains(id));
100
101 threadMap().remove(id);
102}
103
104static ThreadIdentifier identifierByQthreadHandle(QThread*& thread)
105{
106 MutexLocker locker(threadMapMutex());
107
108 HashMap<ThreadIdentifier, QThread*>::iterator i = threadMap().begin();
109 for (; i != threadMap().end(); ++i) {
110 if (i->second == thread)
111 return i->first;
112 }
113
114 return 0;
115}
116
117static QThread* threadForIdentifier(ThreadIdentifier id)
118{
119 MutexLocker locker(threadMapMutex());
120
121 return threadMap().get(id);
122}
123
124void initializeThreading()
125{
126 if(!atomicallyInitializedStaticMutex) {
127 atomicallyInitializedStaticMutex = new Mutex;
128 threadMapMutex();
129 wtf_random_init();
130#if !PLATFORM(DARWIN)
131 mainThreadIdentifier = currentThread();
132#endif
133 initializeMainThread();
134 }
135}
136
137ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*)
138{
139 ThreadPrivate* thread = new ThreadPrivate(entryPoint, data);
140 if (!thread) {
141 LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
142 return 0;
143 }
144 thread->start();
145
146 QThread* threadRef = static_cast<QThread*>(thread);
147
148 return establishIdentifierForThread(threadRef);
149}
150
151int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
152{
153 ASSERT(threadID);
154
155 QThread* thread = threadForIdentifier(threadID);
156
157 bool res = thread->wait();
158
159 clearThreadForIdentifier(threadID);
160 *result = static_cast<ThreadPrivate*>(thread)->getReturnValue();
161
162 return !res;
163}
164
165void detachThread(ThreadIdentifier)
166{
167}
168
169ThreadIdentifier currentThread()
170{
171 QThread* currentThread = QThread::currentThread();
172 if (ThreadIdentifier id = identifierByQthreadHandle(currentThread))
173 return id;
174 return establishIdentifierForThread(currentThread);
175}
176
177bool isMainThread()
178{
179 return currentThread() == mainThreadIdentifier;
180}
181
182Mutex::Mutex()
183 : m_mutex(new QMutex())
184{
185}
186
187Mutex::~Mutex()
188{
189 delete m_mutex;
190}
191
192void Mutex::lock()
193{
194 m_mutex->lock();
195}
196
197bool Mutex::tryLock()
198{
199 return m_mutex->tryLock();
200}
201
202void Mutex::unlock()
203{
204 m_mutex->unlock();
205}
206
207ThreadCondition::ThreadCondition()
208 : m_condition(new QWaitCondition())
209{
210}
211
212ThreadCondition::~ThreadCondition()
213{
214 delete m_condition;
215}
216
217void ThreadCondition::wait(Mutex& mutex)
218{
219 m_condition->wait(mutex.impl());
220}
221
222bool ThreadCondition::timedWait(Mutex& mutex, double secondsToWait)
223{
224 if (secondsToWait < 0.0) {
225 wait(mutex);
226 return true;
227 }
228
229 unsigned long millisecondsToWait = static_cast<unsigned long>(secondsToWait * 1000.0);
230 return m_condition->wait(mutex.impl(), millisecondsToWait);
231}
232
233void ThreadCondition::signal()
234{
235 m_condition->wakeOne();
236}
237
238void ThreadCondition::broadcast()
239{
240 m_condition->wakeAll();
241}
242
243} // namespace WebCore
Note: See TracBrowser for help on using the repository browser.