2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
31 #include "Threading.h"
35 #include "CurrentTime.h"
37 #include "MainThread.h"
38 #include "RandomNumberSeed.h"
39 #include <wtf/StdLibExtras.h>
46 typedef HashMap
<ThreadIdentifier
, GThread
*> ThreadMap
;
48 static Mutex
* atomicallyInitializedStaticMutex
;
50 static Mutex
& threadMapMutex()
52 DEFINE_STATIC_LOCAL(Mutex
, mutex
, ());
56 void initializeThreading()
58 if (!g_thread_supported())
60 ASSERT(g_thread_supported());
62 if (!atomicallyInitializedStaticMutex
) {
63 atomicallyInitializedStaticMutex
= new Mutex
;
65 initializeRandomNumberGenerator();
69 void lockAtomicallyInitializedStaticMutex()
71 ASSERT(atomicallyInitializedStaticMutex
);
72 atomicallyInitializedStaticMutex
->lock();
75 void unlockAtomicallyInitializedStaticMutex()
77 atomicallyInitializedStaticMutex
->unlock();
80 static ThreadMap
& threadMap()
82 DEFINE_STATIC_LOCAL(ThreadMap
, map
, ());
86 static ThreadIdentifier
identifierByGthreadHandle(GThread
*& thread
)
88 MutexLocker
locker(threadMapMutex());
90 ThreadMap::iterator i
= threadMap().begin();
91 for (; i
!= threadMap().end(); ++i
) {
92 if (i
->second
== thread
)
99 static ThreadIdentifier
establishIdentifierForThread(GThread
*& thread
)
101 ASSERT(!identifierByGthreadHandle(thread
));
103 MutexLocker
locker(threadMapMutex());
105 static ThreadIdentifier identifierCount
= 1;
107 threadMap().add(identifierCount
, thread
);
109 return identifierCount
++;
112 static GThread
* threadForIdentifier(ThreadIdentifier id
)
114 MutexLocker
locker(threadMapMutex());
116 return threadMap().get(id
);
119 static void clearThreadForIdentifier(ThreadIdentifier id
)
121 MutexLocker
locker(threadMapMutex());
123 ASSERT(threadMap().contains(id
));
125 threadMap().remove(id
);
128 ThreadIdentifier
createThreadInternal(ThreadFunction entryPoint
, void* data
, const char*)
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
);
136 ThreadIdentifier threadID
= establishIdentifierForThread(thread
);
140 void initializeCurrentThreadInternal(const char*)
144 int waitForThreadCompletion(ThreadIdentifier threadID
, void** result
)
148 GThread
* thread
= threadForIdentifier(threadID
);
150 void* joinResult
= g_thread_join(thread
);
152 *result
= joinResult
;
154 clearThreadForIdentifier(threadID
);
158 void detachThread(ThreadIdentifier
)
162 ThreadIdentifier
currentThread()
164 GThread
* currentThread
= g_thread_self();
165 if (ThreadIdentifier id
= identifierByGthreadHandle(currentThread
))
167 return establishIdentifierForThread(currentThread
);
176 : m_mutex(g_mutex_new())
186 g_mutex_lock(m_mutex
.get());
189 bool Mutex::tryLock()
191 return g_mutex_trylock(m_mutex
.get());
196 g_mutex_unlock(m_mutex
.get());
199 ThreadCondition::ThreadCondition()
200 : m_condition(g_cond_new())
204 ThreadCondition::~ThreadCondition()
208 void ThreadCondition::wait(Mutex
& mutex
)
210 g_cond_wait(m_condition
.get(), mutex
.impl().get());
213 bool ThreadCondition::timedWait(Mutex
& mutex
, double absoluteTime
)
215 // Time is in the past - return right away.
216 if (absoluteTime
< currentTime())
219 // Time is too far in the future for g_cond_timed_wait - wait forever.
220 if (absoluteTime
> INT_MAX
) {
225 int timeSeconds
= static_cast<int>(absoluteTime
);
226 int timeMicroseconds
= static_cast<int>((absoluteTime
- timeSeconds
) * 1000000.0);
229 targetTime
.tv_sec
= timeSeconds
;
230 targetTime
.tv_usec
= timeMicroseconds
;
232 return g_cond_timed_wait(m_condition
.get(), mutex
.impl().get(), &targetTime
);
235 void ThreadCondition::signal()
237 g_cond_signal(m_condition
.get());
240 void ThreadCondition::broadcast()
242 g_cond_broadcast(m_condition
.get());
248 #endif // !USE(PTHREADS)