1 /* 2 * Copyright (C) 2007, 2008, 2010 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 31 #ifndef ThreadingPrimitives_h 32 #define ThreadingPrimitives_h 33 34 #include "wtf/Assertions.h" 35 #include "wtf/FastAllocBase.h" 36 #include "wtf/Locker.h" 37 #include "wtf/Noncopyable.h" 38 #include "wtf/WTFExport.h" 39 40 #if OS(WIN) 41 #include <windows.h> 42 #endif 43 44 #if USE(PTHREADS) 45 #include <pthread.h> 46 #endif 47 48 namespace WTF { 49 50 #if USE(PTHREADS) 51 struct PlatformMutex { 52 pthread_mutex_t m_internalMutex; 53 #if ENABLE(ASSERT) 54 size_t m_recursionCount; 55 #endif 56 }; 57 typedef pthread_cond_t PlatformCondition; 58 #elif OS(WIN) 59 struct PlatformMutex { 60 CRITICAL_SECTION m_internalMutex; 61 size_t m_recursionCount; 62 }; 63 struct PlatformCondition { 64 size_t m_waitersGone; 65 size_t m_waitersBlocked; 66 size_t m_waitersToUnblock; 67 HANDLE m_blockLock; 68 HANDLE m_blockQueue; 69 HANDLE m_unblockLock; 70 71 bool timedWait(PlatformMutex&, DWORD durationMilliseconds); 72 void signal(bool unblockAll); 73 }; 74 #else 75 typedef void* PlatformMutex; 76 typedef void* PlatformCondition; 77 #endif 78 79 class WTF_EXPORT MutexBase { 80 WTF_MAKE_NONCOPYABLE(MutexBase); WTF_MAKE_FAST_ALLOCATED; 81 public: 82 ~MutexBase(); 83 84 void lock(); 85 void unlock(); 86 #if ENABLE(ASSERT) locked()87 bool locked() { return m_mutex.m_recursionCount > 0; } 88 #endif 89 90 public: impl()91 PlatformMutex& impl() { return m_mutex; } 92 93 protected: 94 MutexBase(bool recursive); 95 96 PlatformMutex m_mutex; 97 }; 98 99 class WTF_EXPORT Mutex : public MutexBase { 100 public: Mutex()101 Mutex() : MutexBase(false) { } 102 bool tryLock(); 103 }; 104 105 class WTF_EXPORT RecursiveMutex : public MutexBase { 106 public: RecursiveMutex()107 RecursiveMutex() : MutexBase(true) { } 108 bool tryLock(); 109 }; 110 111 typedef Locker<MutexBase> MutexLocker; 112 113 class MutexTryLocker { 114 WTF_MAKE_NONCOPYABLE(MutexTryLocker); 115 public: MutexTryLocker(Mutex & mutex)116 MutexTryLocker(Mutex& mutex) : m_mutex(mutex), m_locked(mutex.tryLock()) { } ~MutexTryLocker()117 ~MutexTryLocker() 118 { 119 if (m_locked) 120 m_mutex.unlock(); 121 } 122 locked()123 bool locked() const { return m_locked; } 124 125 private: 126 Mutex& m_mutex; 127 bool m_locked; 128 }; 129 130 class WTF_EXPORT ThreadCondition { 131 WTF_MAKE_NONCOPYABLE(ThreadCondition); 132 public: 133 ThreadCondition(); 134 ~ThreadCondition(); 135 136 void wait(MutexBase&); 137 // Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past. 138 // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). 139 bool timedWait(MutexBase&, double absoluteTime); 140 void signal(); 141 void broadcast(); 142 143 private: 144 PlatformCondition m_condition; 145 }; 146 147 #if OS(WIN) 148 // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). 149 // Returns an interval in milliseconds suitable for passing to one of the Win32 wait functions (e.g., ::WaitForSingleObject). 150 DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime); 151 #endif 152 153 } // namespace WTF 154 155 using WTF::MutexBase; 156 using WTF::Mutex; 157 using WTF::RecursiveMutex; 158 using WTF::MutexLocker; 159 using WTF::MutexTryLocker; 160 using WTF::ThreadCondition; 161 162 #if OS(WIN) 163 using WTF::absoluteTimeToWaitTimeoutInterval; 164 #endif 165 166 #endif // ThreadingPrimitives_h 167