2007-12-18 Rodney Dawes <dobey@wayofthemonkey.com>
[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 #ifndef Threading_h
31 #define Threading_h
32
33 #include <wtf/Assertions.h>
34 #include <wtf/Noncopyable.h>
35
36 #if USE(PTHREADS)
37 #include <pthread.h>
38 #endif
39
40 #if PLATFORM(GTK)
41 typedef struct _GMutex GMutex;
42 typedef struct _GCond GCond;
43 #endif
44
45 #if PLATFORM(QT)
46 class QMutex;
47 class QWaitCondition;
48 #endif
49
50 #include <stdint.h>
51
52 namespace WebCore {
53
54 typedef uint32_t ThreadIdentifier;
55 typedef void* (*ThreadFunction)(void* argument);
56
57 // Returns 0 if thread creation failed
58 ThreadIdentifier createThread(ThreadFunction, void*);
59 ThreadIdentifier currentThread();
60 int waitForThreadCompletion(ThreadIdentifier, void**);
61 void detachThread(ThreadIdentifier);
62
63 #if USE(PTHREADS)
64 typedef pthread_mutex_t PlatformMutex;
65 typedef pthread_cond_t PlatformCondition;
66 #elif PLATFORM(GTK)
67 typedef GMutex* PlatformMutex;
68 typedef GCond* PlatformCondition;
69 #elif PLATFORM(QT)
70 typedef QMutex* PlatformMutex;
71 typedef QWaitCondition* PlatformCondition;
72 #else
73 typedef void* PlatformMutex;
74 typedef void* PlatformCondition;
75 #endif
76     
77 class Mutex : Noncopyable {
78 public:
79     Mutex();
80     ~Mutex();
81
82     void lock();
83     bool tryLock();
84     void unlock();
85
86 public:
87     PlatformMutex& impl() { return m_mutex; }
88 private:
89     PlatformMutex m_mutex;
90 };
91
92 class MutexLocker : Noncopyable {
93 public:
94     MutexLocker(Mutex& mutex) : m_mutex(mutex) { m_mutex.lock(); }
95     ~MutexLocker() { m_mutex.unlock(); }
96
97 private:
98     Mutex& m_mutex;
99 };
100
101 class ThreadCondition : Noncopyable {
102 public:
103     ThreadCondition();
104     ~ThreadCondition();
105     
106     void wait(Mutex& mutex);
107     void signal();
108     void broadcast();
109     
110 private:
111     PlatformCondition m_condition;
112 };
113     
114 template<class T> class ThreadSafeShared : Noncopyable {
115 public:
116     ThreadSafeShared()
117         : m_refCount(0)
118 #ifndef NDEBUG
119         , m_inDestructor(0)
120 #endif
121     {
122     }
123
124     void ref()
125     {
126         MutexLocker locker(m_mutex);
127         ASSERT(!m_inDestructor);
128         ++m_refCount;
129     }
130
131     void deref()
132     {
133         {
134             MutexLocker locker(m_mutex);
135             ASSERT(!m_inDestructor);
136             --m_refCount;
137         }
138         
139         if (m_refCount <= 0) {
140 #ifndef NDEBUG
141             m_inDestructor = true;
142 #endif
143             delete static_cast<T*>(this);
144         }
145     }
146
147     bool hasOneRef()
148     {
149         MutexLocker locker(m_mutex);
150         ASSERT(!m_inDestructor);
151         return m_refCount == 1;
152     }
153
154     int refCount() const
155     {
156         MutexLocker locker(m_mutex);
157         return m_refCount;
158     }
159
160     bool isThreadSafe() { return true; }
161     
162 private:
163     mutable Mutex m_mutex;
164     int m_refCount;
165 #ifndef NDEBUG
166     bool m_inDestructor;
167 #endif
168 };
169
170 void callOnMainThread(void (*)());
171
172 void initializeThreading();
173
174 #if !PLATFORM(WIN) && !PLATFORM(GTK)
175 inline void initializeThreading()
176 {
177 }
178 #endif
179
180 } // namespace WebCore
181
182 #endif // Threading_h