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 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.  
  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. 
  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. 
  34  * Boost Software License - Version 1.0 - August 17th, 2003 
  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: 
  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. 
  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. 
  68 #include <wtf/Assertions.h> 
  69 #include <wtf/Locker.h> 
  70 #include <wtf/Noncopyable.h> 
  72 #if OS(WINDOWS) && !OS(WINCE) 
  75 #include <libkern/OSAtomic.h> 
  77 #include <cutils/atomic.h> 
  79 #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) 
  80 #include <ext/atomicity.h> 
  82 #include <bits/atomicity.h> 
  89 #include <wtf/gtk/GOwnPtr.h> 
  90 typedef struct _GMutex GMutex
; 
  91 typedef struct _GCond GCond
; 
 104 // For portability, we do not use thread-safe statics natively supported by some compilers (e.g. gcc). 
 105 #define AtomicallyInitializedStatic(T, name) \ 
 106     WTF::lockAtomicallyInitializedStaticMutex(); \ 
 108     WTF::unlockAtomicallyInitializedStaticMutex(); 
 112 typedef uint32_t ThreadIdentifier
; 
 113 typedef void* (*ThreadFunction
)(void* argument
); 
 115 // Returns 0 if thread creation failed. 
 116 // The thread name must be a literal since on some platforms it's passed in to the thread. 
 117 ThreadIdentifier 
createThread(ThreadFunction
, void*, const char* threadName
); 
 119 // Internal platform-specific createThread implementation. 
 120 ThreadIdentifier 
createThreadInternal(ThreadFunction
, void*, const char* threadName
); 
 122 // Called in the thread during initialization. 
 123 // Helpful for platforms where the thread name must be set from within the thread. 
 124 void initializeCurrentThreadInternal(const char* threadName
); 
 126 ThreadIdentifier 
currentThread(); 
 128 int waitForThreadCompletion(ThreadIdentifier
, void**); 
 129 void detachThread(ThreadIdentifier
); 
 132 typedef pthread_mutex_t PlatformMutex
; 
 133 #if HAVE(PTHREAD_RWLOCK) 
 134 typedef pthread_rwlock_t PlatformReadWriteLock
; 
 136 typedef void* PlatformReadWriteLock
; 
 138 typedef pthread_cond_t PlatformCondition
; 
 140 typedef GOwnPtr
<GMutex
> PlatformMutex
; 
 141 typedef void* PlatformReadWriteLock
; // FIXME: Implement. 
 142 typedef GOwnPtr
<GCond
> PlatformCondition
; 
 144 typedef QT_PREPEND_NAMESPACE(QMutex
)* PlatformMutex
; 
 145 typedef void* PlatformReadWriteLock
; // FIXME: Implement. 
 146 typedef QT_PREPEND_NAMESPACE(QWaitCondition
)* PlatformCondition
; 
 148 struct PlatformMutex 
{ 
 149     CRITICAL_SECTION m_internalMutex
; 
 150     size_t m_recursionCount
; 
 152 typedef void* PlatformReadWriteLock
; // FIXME: Implement. 
 153 struct PlatformCondition 
{ 
 154     size_t m_waitersGone
; 
 155     size_t m_waitersBlocked
; 
 156     size_t m_waitersToUnblock
;  
 159     HANDLE m_unblockLock
; 
 161     bool timedWait(PlatformMutex
&, DWORD durationMilliseconds
); 
 162     void signal(bool unblockAll
); 
 165 typedef void* PlatformMutex
; 
 166 typedef void* PlatformReadWriteLock
; 
 167 typedef void* PlatformCondition
; 
 170 class Mutex 
: public Noncopyable 
{ 
 180     PlatformMutex
& impl() { return m_mutex
; } 
 182     PlatformMutex m_mutex
; 
 185 typedef Locker
<Mutex
> MutexLocker
; 
 187 class ReadWriteLock 
: public Noncopyable 
{ 
 201     PlatformReadWriteLock m_readWriteLock
; 
 204 class ThreadCondition 
: public Noncopyable 
{ 
 209     void wait(Mutex
& mutex
); 
 210     // Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past. 
 211     // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). 
 212     bool timedWait(Mutex
&, double absoluteTime
); 
 217     PlatformCondition m_condition
; 
 221 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 
 223 #if COMPILER(MINGW) || COMPILER(MSVC7) || OS(WINCE) 
 224 inline int atomicIncrement(int* addend
) { return InterlockedIncrement(reinterpret_cast<long*>(addend
)); } 
 225 inline int atomicDecrement(int* addend
) { return InterlockedDecrement(reinterpret_cast<long*>(addend
)); } 
 227 inline int atomicIncrement(int volatile* addend
) { return InterlockedIncrement(reinterpret_cast<long volatile*>(addend
)); } 
 228 inline int atomicDecrement(int volatile* addend
) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend
)); } 
 232 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 
 234 inline int atomicIncrement(int volatile* addend
) { return OSAtomicIncrement32Barrier(const_cast<int*>(addend
)); } 
 235 inline int atomicDecrement(int volatile* addend
) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend
)); } 
 239 inline int atomicIncrement(int volatile* addend
) { return android_atomic_inc(addend
); } 
 240 inline int atomicDecrement(int volatile* addend
) { return android_atomic_dec(addend
); } 
 242 #elif COMPILER(GCC) && !CPU(SPARC64) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc 
 243 #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 
 245 inline int atomicIncrement(int volatile* addend
) { return __gnu_cxx::__exchange_and_add(addend
, 1) + 1; } 
 246 inline int atomicDecrement(int volatile* addend
) { return __gnu_cxx::__exchange_and_add(addend
, -1) - 1; } 
 250 class ThreadSafeSharedBase 
: public Noncopyable 
{ 
 252     ThreadSafeSharedBase(int initialRefCount 
= 1) 
 253         : m_refCount(initialRefCount
) 
 259 #if USE(LOCKFREE_THREADSAFESHARED) 
 260         atomicIncrement(&m_refCount
); 
 262         MutexLocker 
locker(m_mutex
); 
 269         return refCount() == 1; 
 274 #if !USE(LOCKFREE_THREADSAFESHARED) 
 275         MutexLocker 
locker(m_mutex
); 
 277         return static_cast<int const volatile &>(m_refCount
); 
 281     // Returns whether the pointer should be freed or not. 
 284 #if USE(LOCKFREE_THREADSAFESHARED) 
 285         if (atomicDecrement(&m_refCount
) <= 0) 
 290             MutexLocker 
locker(m_mutex
); 
 292             refCount 
= m_refCount
; 
 302     friend class CrossThreadRefCounted
; 
 305 #if !USE(LOCKFREE_THREADSAFESHARED) 
 306     mutable Mutex m_mutex
; 
 310 template<class T
> class ThreadSafeShared 
: public ThreadSafeSharedBase 
{ 
 312     ThreadSafeShared(int initialRefCount 
= 1) 
 313         : ThreadSafeSharedBase(initialRefCount
) 
 320             delete static_cast<T
*>(this); 
 324 // This function must be called from the main thread. It is safe to call it repeatedly. 
 325 // Darwin is an exception to this rule: it is OK to call it from any thread, the only requirement is that the calls are not reentrant. 
 326 void initializeThreading(); 
 328 void lockAtomicallyInitializedStaticMutex(); 
 329 void unlockAtomicallyInitializedStaticMutex(); 
 334 using WTF::MutexLocker
; 
 335 using WTF::ThreadCondition
; 
 336 using WTF::ThreadIdentifier
; 
 337 using WTF::ThreadSafeShared
; 
 339 #if USE(LOCKFREE_THREADSAFESHARED) 
 340 using WTF::atomicDecrement
; 
 341 using WTF::atomicIncrement
; 
 344 using WTF::createThread
; 
 345 using WTF::currentThread
; 
 346 using WTF::isMainThread
; 
 347 using WTF::detachThread
; 
 348 using WTF::waitForThreadCompletion
; 
 350 #endif // Threading_h