]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/ThreadingGtk.cpp
JavaScriptCore-525.tar.gz
[apple/javascriptcore.git] / wtf / 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 int waitForThreadCompletion(ThreadIdentifier threadID, void** result)
142 {
143 ASSERT(threadID);
144
145 GThread* thread = threadForIdentifier(threadID);
146
147 void* joinResult = g_thread_join(thread);
148 if (result)
149 *result = joinResult;
150
151 clearThreadForIdentifier(threadID);
152 return 0;
153 }
154
155 void detachThread(ThreadIdentifier)
156 {
157 }
158
159 ThreadIdentifier currentThread()
160 {
161 GThread* currentThread = g_thread_self();
162 if (ThreadIdentifier id = identifierByGthreadHandle(currentThread))
163 return id;
164 return establishIdentifierForThread(currentThread);
165 }
166
167 bool isMainThread()
168 {
169 return currentThread() == mainThreadIdentifier;
170 }
171
172 Mutex::Mutex()
173 : m_mutex(g_mutex_new())
174 {
175 }
176
177 Mutex::~Mutex()
178 {
179 }
180
181 void Mutex::lock()
182 {
183 g_mutex_lock(m_mutex.get());
184 }
185
186 bool Mutex::tryLock()
187 {
188 return g_mutex_trylock(m_mutex.get());
189 }
190
191 void Mutex::unlock()
192 {
193 g_mutex_unlock(m_mutex.get());
194 }
195
196 ThreadCondition::ThreadCondition()
197 : m_condition(g_cond_new())
198 {
199 }
200
201 ThreadCondition::~ThreadCondition()
202 {
203 }
204
205 void ThreadCondition::wait(Mutex& mutex)
206 {
207 g_cond_wait(m_condition.get(), mutex.impl().get());
208 }
209
210 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
211 {
212 // Time is in the past - return right away.
213 if (absoluteTime < currentTime())
214 return false;
215
216 // Time is too far in the future for g_cond_timed_wait - wait forever.
217 if (absoluteTime > INT_MAX) {
218 wait(mutex);
219 return true;
220 }
221
222 int timeSeconds = static_cast<int>(absoluteTime);
223 int timeMicroseconds = static_cast<int>((absoluteTime - timeSeconds) * 1000000.0);
224
225 GTimeVal targetTime;
226 targetTime.tv_sec = timeSeconds;
227 targetTime.tv_usec = timeMicroseconds;
228
229 return g_cond_timed_wait(m_condition.get(), mutex.impl().get(), &targetTime);
230 }
231
232 void ThreadCondition::signal()
233 {
234 g_cond_signal(m_condition.get());
235 }
236
237 void ThreadCondition::broadcast()
238 {
239 g_cond_broadcast(m_condition.get());
240 }
241
242
243 }
244
245 #endif // !USE(PTHREADS)