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