source: webkit/trunk/JavaScriptCore/wtf/ThreadingGtk.cpp@ 36056

Last change on this file since 36056 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.
  • Property svn:eol-style set to native
File size: 5.5 KB
Line 
1/*
2 * Copyright (C) 2007, 2008 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 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#include "config.h"
31#include "Threading.h"
32
33#include "HashMap.h"
34#include "MainThread.h"
35#include "MathExtras.h"
36
37#include <glib.h>
38
39namespace WTF {
40
41Mutex* atomicallyInitializedStaticMutex;
42
43#if !PLATFORM(DARWIN)
44static ThreadIdentifier mainThreadIdentifier;
45#endif
46
47static Mutex& threadMapMutex()
48{
49 static Mutex mutex;
50 return mutex;
51}
52
53void initializeThreading()
54{
55 if (!g_thread_supported())
56 g_thread_init(NULL);
57 ASSERT(g_thread_supported());
58
59 if (!atomicallyInitializedStaticMutex) {
60 atomicallyInitializedStaticMutex = new Mutex;
61 threadMapMutex();
62 wtf_random_init();
63#if !PLATFORM(DARWIN)
64 mainThreadIdentifier = currentThread();
65#endif
66 initializeMainThread();
67 }
68}
69
70static HashMap<ThreadIdentifier, GThread*>& threadMap()
71{
72 static HashMap<ThreadIdentifier, GThread*> map;
73 return map;
74}
75
76static ThreadIdentifier establishIdentifierForThread(GThread*& thread)
77{
78 MutexLocker locker(threadMapMutex());
79
80 static ThreadIdentifier identifierCount = 1;
81
82 threadMap().add(identifierCount, thread);
83
84 return identifierCount++;
85}
86
87static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
88{
89 MutexLocker locker(threadMapMutex());
90
91 HashMap<ThreadIdentifier, GThread*>::iterator i = threadMap().begin();
92 for (; i != threadMap().end(); ++i) {
93 if (i->second == thread)
94 return i->first;
95 }
96
97 return 0;
98}
99
100static GThread* threadForIdentifier(ThreadIdentifier id)
101{
102 MutexLocker locker(threadMapMutex());
103
104 return threadMap().get(id);
105}
106
107static void clearThreadForIdentifier(ThreadIdentifier id)
108{
109 MutexLocker locker(threadMapMutex());
110
111 ASSERT(threadMap().contains(id));
112
113 threadMap().remove(id);
114}
115
116ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char*)
117{
118 GThread* thread;
119 if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) {
120 LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
121 return 0;
122 }
123
124 ThreadIdentifier threadID = establishIdentifierForThread(thread);
125 return threadID;
126}
127
128int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
129{
130 ASSERT(threadID);
131
132 GThread* thread = threadForIdentifier(threadID);
133
134 *result = g_thread_join(thread);
135
136 clearThreadForIdentifier(threadID);
137 return 0;
138}
139
140void detachThread(ThreadIdentifier)
141{
142}
143
144ThreadIdentifier currentThread()
145{
146 GThread* currentThread = g_thread_self();
147 if (ThreadIdentifier id = identifierByGthreadHandle(currentThread))
148 return id;
149 return establishIdentifierForThread(currentThread);
150}
151
152bool isMainThread()
153{
154 return currentThread() == mainThreadIdentifier;
155}
156
157Mutex::Mutex()
158 : m_mutex(g_mutex_new())
159{
160}
161
162Mutex::~Mutex()
163{
164 g_mutex_free(m_mutex);
165}
166
167void Mutex::lock()
168{
169 g_mutex_lock(m_mutex);
170}
171
172bool Mutex::tryLock()
173{
174 return g_mutex_trylock(m_mutex);
175}
176
177void Mutex::unlock()
178{
179 g_mutex_unlock(m_mutex);
180}
181
182ThreadCondition::ThreadCondition()
183 : m_condition(g_cond_new())
184{
185}
186
187ThreadCondition::~ThreadCondition()
188{
189 g_cond_free(m_condition);
190}
191
192void ThreadCondition::wait(Mutex& mutex)
193{
194 g_cond_wait(m_condition, mutex.impl());
195}
196
197bool ThreadCondition::timedWait(Mutex& mutex, double interval)
198{
199 if (interval < 0.0) {
200 wait(mutex);
201 return true;
202 }
203
204 int intervalSeconds = static_cast<int>(interval);
205 int intervalMicroseconds = static_cast<int>((interval - intervalSeconds) * 1000000.0);
206
207 GTimeVal targetTime;
208 g_get_current_time(&targetTime);
209
210 targetTime.tv_sec += intervalSeconds;
211 targetTime.tv_usec += intervalMicroseconds;
212 if (targetTime.tv_usec > 1000000) {
213 targetTime.tv_usec -= 1000000;
214 targetTime.tv_sec++;
215 }
216
217 return g_cond_timed_wait(m_condition, mutex.impl(), &targetTime);
218}
219
220void ThreadCondition::signal()
221{
222 g_cond_signal(m_condition);
223}
224
225void ThreadCondition::broadcast()
226{
227 g_cond_broadcast(m_condition);
228}
229
230
231}
Note: See TracBrowser for help on using the repository browser.