Tiger build fix.
[WebKit-https.git] / WebCore / platform / Threading.h
1 /*
2  * Copyright (C) 2007 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 Computer, 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  * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based
31  * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license
32  * is virtually identical to the Apple license above but is included here for completeness.
33  *
34  * Boost Software License - Version 1.0 - August 17th, 2003
35  * 
36  * Permission is hereby granted, free of charge, to any person or organization
37  * obtaining a copy of the software and accompanying documentation covered by
38  * this license (the "Software") to use, reproduce, display, distribute,
39  * execute, and transmit the Software, and to prepare derivative works of the
40  * Software, and to permit third-parties to whom the Software is furnished to
41  * do so, all subject to the following:
42  * 
43  * The copyright notices in the Software and this entire statement, including
44  * the above license grant, this restriction and the following disclaimer,
45  * must be included in all copies of the Software, in whole or in part, and
46  * all derivative works of the Software, unless such copies or derivative
47  * works are solely in the form of machine-executable object code generated by
48  * a source language processor.
49  * 
50  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
53  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
54  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
55  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
56  * DEALINGS IN THE SOFTWARE.
57  */
58
59 #ifndef Threading_h
60 #define Threading_h
61
62 #include <wtf/Assertions.h>
63 #include <wtf/Noncopyable.h>
64
65 #if PLATFORM(WIN_OS)
66 #include <windows.h>
67 #elif PLATFORM(DARWIN)
68 #include <libkern/OSAtomic.h>
69 #elif COMPILER(GCC)
70 #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2))
71 #include <ext/atomicity.h>
72 #else
73 #include <bits/atomicity.h>
74 #endif
75 #endif
76
77 #if USE(PTHREADS)
78 #include <pthread.h>
79 #endif
80
81 #if PLATFORM(GTK)
82 typedef struct _GMutex GMutex;
83 typedef struct _GCond GCond;
84 #endif
85
86 #if PLATFORM(QT)
87 class QMutex;
88 class QWaitCondition;
89 #endif
90
91 #include <stdint.h>
92
93 namespace WebCore {
94
95 typedef uint32_t ThreadIdentifier;
96 typedef void* (*ThreadFunction)(void* argument);
97
98 // Returns 0 if thread creation failed
99 ThreadIdentifier createThread(ThreadFunction, void*);
100 ThreadIdentifier currentThread();
101 int waitForThreadCompletion(ThreadIdentifier, void**);
102 void detachThread(ThreadIdentifier);
103
104 #if USE(PTHREADS)
105 typedef pthread_mutex_t PlatformMutex;
106 typedef pthread_cond_t PlatformCondition;
107 #elif PLATFORM(GTK)
108 typedef GMutex* PlatformMutex;
109 typedef GCond* PlatformCondition;
110 #elif PLATFORM(QT)
111 typedef QMutex* PlatformMutex;
112 typedef QWaitCondition* PlatformCondition;
113 #elif PLATFORM(WIN_OS)
114 struct PlatformMutex {
115     CRITICAL_SECTION m_internalMutex;
116     size_t m_recursionCount;
117 };
118 struct PlatformCondition {
119     size_t m_timedOut;
120     size_t m_blocked;
121     size_t m_waitingForRemoval;
122     HANDLE m_gate;
123     HANDLE m_queue;
124     HANDLE m_mutex;
125 };
126 #else
127 typedef void* PlatformMutex;
128 typedef void* PlatformCondition;
129 #endif
130     
131 class Mutex : Noncopyable {
132 public:
133     Mutex();
134     ~Mutex();
135
136     void lock();
137     bool tryLock();
138     void unlock();
139
140 public:
141     PlatformMutex& impl() { return m_mutex; }
142 private:
143     PlatformMutex m_mutex;
144 };
145
146 class MutexLocker : Noncopyable {
147 public:
148     MutexLocker(Mutex& mutex) : m_mutex(mutex) { m_mutex.lock(); }
149     ~MutexLocker() { m_mutex.unlock(); }
150
151 private:
152     Mutex& m_mutex;
153 };
154
155 class ThreadCondition : Noncopyable {
156 public:
157     ThreadCondition();
158     ~ThreadCondition();
159     
160     void wait(Mutex& mutex);
161     void signal();
162     void broadcast();
163     
164 private:
165     PlatformCondition m_condition;
166 };
167
168 #if PLATFORM(WIN_OS)
169 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1
170
171 inline void atomicIncrement(int volatile* addend) { InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); }
172 inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); }
173
174 #elif PLATFORM(DARWIN)
175 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1
176
177 inline void atomicIncrement(int volatile* addend) { OSAtomicIncrement32Barrier(const_cast<int*>(addend)); }
178 inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); }
179
180 #elif COMPILER(GCC)
181 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1
182
183 inline void atomicIncrement(int volatile* addend) { __gnu_cxx::__atomic_add(addend, 1); }
184 inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; }
185
186 #endif
187
188 template<class T> class ThreadSafeShared : Noncopyable {
189 public:
190     ThreadSafeShared()
191         : m_refCount(0)
192     {
193     }
194
195     void ref()
196     {
197 #if USE(LOCKFREE_THREADSAFESHARED)
198         atomicIncrement(&m_refCount);
199 #else
200         MutexLocker locker(m_mutex);
201         ++m_refCount;
202 #endif
203     }
204
205     void deref()
206     {
207 #if USE(LOCKFREE_THREADSAFESHARED)
208         if (atomicDecrement(&m_refCount) <= 0)
209 #else
210         {
211             MutexLocker locker(m_mutex);
212             --m_refCount;
213         }
214         if (m_refCount <= 0)
215 #endif
216             delete static_cast<T*>(this);
217     }
218
219     bool hasOneRef()
220     {
221         return refCount() == 1;
222     }
223
224     int refCount() const
225     {
226 #if !USE(LOCKFREE_THREADSAFESHARED)
227         MutexLocker locker(m_mutex);
228 #endif
229         return static_cast<int const volatile &>(m_refCount);
230     }
231
232 private:
233     int m_refCount;
234 #if !USE(LOCKFREE_THREADSAFESHARED)
235     mutable Mutex m_mutex;
236 #endif
237 };
238
239 void callOnMainThread(void (*)());
240
241 void initializeThreading();
242
243 #if !PLATFORM(WIN) && !PLATFORM(GTK)
244 inline void initializeThreading()
245 {
246 }
247 #endif
248
249 } // namespace WebCore
250
251 #endif // Threading_h