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