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