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"
45 static Mutex
* atomicallyInitializedStaticMutex
;
47 static ThreadIdentifier mainThreadIdentifier
;
49 static Mutex
& threadMapMutex()
55 void initializeThreading()
57 if (!g_thread_supported())
59 ASSERT(g_thread_supported());
61 if (!atomicallyInitializedStaticMutex
) {
62 atomicallyInitializedStaticMutex
= new Mutex
;
64 initializeRandomNumberGenerator();
65 mainThreadIdentifier
= currentThread();
66 initializeMainThread();
70 void lockAtomicallyInitializedStaticMutex()
72 ASSERT(atomicallyInitializedStaticMutex
);
73 atomicallyInitializedStaticMutex
->lock();
76 void unlockAtomicallyInitializedStaticMutex()
78 atomicallyInitializedStaticMutex
->unlock();
81 static HashMap
<ThreadIdentifier
, GThread
*>& threadMap()
83 static HashMap
<ThreadIdentifier
, GThread
*> map
;
87 static ThreadIdentifier
identifierByGthreadHandle(GThread
*& thread
)
89 MutexLocker
locker(threadMapMutex());
91 HashMap
<ThreadIdentifier
, GThread
*>::iterator i
= threadMap().begin();
92 for (; i
!= threadMap().end(); ++i
) {
93 if (i
->second
== thread
)
100 static ThreadIdentifier
establishIdentifierForThread(GThread
*& thread
)
102 ASSERT(!identifierByGthreadHandle(thread
));
104 MutexLocker
locker(threadMapMutex());
106 static ThreadIdentifier identifierCount
= 1;
108 threadMap().add(identifierCount
, thread
);
110 return identifierCount
++;
113 static GThread
* threadForIdentifier(ThreadIdentifier id
)
115 MutexLocker
locker(threadMapMutex());
117 return threadMap().get(id
);
120 static void clearThreadForIdentifier(ThreadIdentifier id
)
122 MutexLocker
locker(threadMapMutex());
124 ASSERT(threadMap().contains(id
));
126 threadMap().remove(id
);
129 ThreadIdentifier
createThreadInternal(ThreadFunction entryPoint
, void* data
, const char*)
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
);
137 ThreadIdentifier threadID
= establishIdentifierForThread(thread
);
141 int waitForThreadCompletion(ThreadIdentifier threadID
, void** result
)
145 GThread
* thread
= threadForIdentifier(threadID
);
147 void* joinResult
= g_thread_join(thread
);
149 *result
= joinResult
;
151 clearThreadForIdentifier(threadID
);
155 void detachThread(ThreadIdentifier
)
159 ThreadIdentifier
currentThread()
161 GThread
* currentThread
= g_thread_self();
162 if (ThreadIdentifier id
= identifierByGthreadHandle(currentThread
))
164 return establishIdentifierForThread(currentThread
);
169 return currentThread() == mainThreadIdentifier
;
173 : m_mutex(g_mutex_new())
183 g_mutex_lock(m_mutex
.get());
186 bool Mutex::tryLock()
188 return g_mutex_trylock(m_mutex
.get());
193 g_mutex_unlock(m_mutex
.get());
196 ThreadCondition::ThreadCondition()
197 : m_condition(g_cond_new())
201 ThreadCondition::~ThreadCondition()
205 void ThreadCondition::wait(Mutex
& mutex
)
207 g_cond_wait(m_condition
.get(), mutex
.impl().get());
210 bool ThreadCondition::timedWait(Mutex
& mutex
, double absoluteTime
)
212 // Time is in the past - return right away.
213 if (absoluteTime
< currentTime())
216 // Time is too far in the future for g_cond_timed_wait - wait forever.
217 if (absoluteTime
> INT_MAX
) {
222 int timeSeconds
= static_cast<int>(absoluteTime
);
223 int timeMicroseconds
= static_cast<int>((absoluteTime
- timeSeconds
) * 1000000.0);
226 targetTime
.tv_sec
= timeSeconds
;
227 targetTime
.tv_usec
= timeMicroseconds
;
229 return g_cond_timed_wait(m_condition
.get(), mutex
.impl().get(), &targetTime
);
232 void ThreadCondition::signal()
234 g_cond_signal(m_condition
.get());
237 void ThreadCondition::broadcast()
239 g_cond_broadcast(m_condition
.get());
245 #endif // !USE(PTHREADS)