]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/gtk/ThreadingGtk.cpp
JavaScriptCore-554.1.tar.gz
[apple/javascriptcore.git] / wtf / gtk / ThreadingGtk.cpp
1 /*
2 * Copyright (C) 2007, 2008 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 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 #if !USE(PTHREADS)
34
35 #include "CurrentTime.h"
36 #include "HashMap.h"
37 #include "MainThread.h"
38 #include "RandomNumberSeed.h"
39
40 #include <glib.h>
41 #include <limits.h>
42
43 namespace WTF {
44
45 static Mutex* atomicallyInitializedStaticMutex;
46
47 static ThreadIdentifier mainThreadIdentifier;
48
49 static Mutex& threadMapMutex()
50 {
51 static Mutex mutex;
52 return mutex;
53 }
54
55 void initializeThreading()
56 {
57 if (!g_thread_supported())
58 g_thread_init(NULL);
59 ASSERT(g_thread_supported());
60
61 if (!atomicallyInitializedStaticMutex) {
62 atomicallyInitializedStaticMutex = new Mutex;
63 threadMapMutex();
64 initializeRandomNumberGenerator();
65 mainThreadIdentifier = currentThread();
66 initializeMainThread();
67 }
68 }
69
70 void lockAtomicallyInitializedStaticMutex()
71 {
72 ASSERT(atomicallyInitializedStaticMutex);
73 atomicallyInitializedStaticMutex->lock();
74 }
75
76 void unlockAtomicallyInitializedStaticMutex()
77 {
78 atomicallyInitializedStaticMutex->unlock();
79 }
80
81 static HashMap<ThreadIdentifier, GThread*>& threadMap()
82 {
83 static HashMap<ThreadIdentifier, GThread*> map;
84 return map;
85 }
86
87 static 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
100 static ThreadIdentifier establishIdentifierForThread(GThread*& thread)
101 {
102 ASSERT(!identifierByGthreadHandle(thread));
103
104 MutexLocker locker(threadMapMutex());
105
106 static ThreadIdentifier identifierCount = 1;
107
108 threadMap().add(identifierCount, thread);
109
110 return identifierCount++;
111 }
112
113 static GThread* threadForIdentifier(ThreadIdentifier id)
114 {
115 MutexLocker locker(threadMapMutex());
116
117 return threadMap().get(id);
118 }
119
120 static void clearThreadForIdentifier(ThreadIdentifier id)
121 {
122 MutexLocker locker(threadMapMutex());
123
124 ASSERT(threadMap().contains(id));
125
126 threadMap().remove(id);
127 }
128
129 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
130 {
131 GThread* thread;
132 if (!(thread = g_thread_create(entryPoint, data, TRUE, 0))) {
133 LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data);
134 return 0;
135 }
136
137 ThreadIdentifier threadID = establishIdentifierForThread(thread);
138 return threadID;
139 }
140
141 void setThreadNameInternal(const char*)
142 {
143 }
144
145 int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
146 {
147 ASSERT(threadID);
148
149 GThread* thread = threadForIdentifier(threadID);
150
151 void* joinResult = g_thread_join(thread);
152 if (result)
153 *result = joinResult;
154
155 clearThreadForIdentifier(threadID);
156 return 0;
157 }
158
159 void detachThread(ThreadIdentifier)
160 {
161 }
162
163 ThreadIdentifier currentThread()
164 {
165 GThread* currentThread = g_thread_self();
166 if (ThreadIdentifier id = identifierByGthreadHandle(currentThread))
167 return id;
168 return establishIdentifierForThread(currentThread);
169 }
170
171 bool isMainThread()
172 {
173 return currentThread() == mainThreadIdentifier;
174 }
175
176 Mutex::Mutex()
177 : m_mutex(g_mutex_new())
178 {
179 }
180
181 Mutex::~Mutex()
182 {
183 }
184
185 void Mutex::lock()
186 {
187 g_mutex_lock(m_mutex.get());
188 }
189
190 bool Mutex::tryLock()
191 {
192 return g_mutex_trylock(m_mutex.get());
193 }
194
195 void Mutex::unlock()
196 {
197 g_mutex_unlock(m_mutex.get());
198 }
199
200 ThreadCondition::ThreadCondition()
201 : m_condition(g_cond_new())
202 {
203 }
204
205 ThreadCondition::~ThreadCondition()
206 {
207 }
208
209 void ThreadCondition::wait(Mutex& mutex)
210 {
211 g_cond_wait(m_condition.get(), mutex.impl().get());
212 }
213
214 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
215 {
216 // Time is in the past - return right away.
217 if (absoluteTime < currentTime())
218 return false;
219
220 // Time is too far in the future for g_cond_timed_wait - wait forever.
221 if (absoluteTime > INT_MAX) {
222 wait(mutex);
223 return true;
224 }
225
226 int timeSeconds = static_cast<int>(absoluteTime);
227 int timeMicroseconds = static_cast<int>((absoluteTime - timeSeconds) * 1000000.0);
228
229 GTimeVal targetTime;
230 targetTime.tv_sec = timeSeconds;
231 targetTime.tv_usec = timeMicroseconds;
232
233 return g_cond_timed_wait(m_condition.get(), mutex.impl().get(), &targetTime);
234 }
235
236 void ThreadCondition::signal()
237 {
238 g_cond_signal(m_condition.get());
239 }
240
241 void ThreadCondition::broadcast()
242 {
243 g_cond_broadcast(m_condition.get());
244 }
245
246
247 }
248
249 #endif // !USE(PTHREADS)