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
48namespace WTF {
49
50#if USE(PTHREADS)
51struct PlatformMutex {
52    pthread_mutex_t m_internalMutex;
53#if ENABLE(ASSERT)
54    size_t m_recursionCount;
55#endif
56};
57typedef pthread_cond_t PlatformCondition;
58#elif OS(WIN)
59struct PlatformMutex {
60    CRITICAL_SECTION m_internalMutex;
61    size_t m_recursionCount;
62};
63struct 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
75typedef void* PlatformMutex;
76typedef void* PlatformCondition;
77#endif
78
79class WTF_EXPORT MutexBase {
80    WTF_MAKE_NONCOPYABLE(MutexBase); WTF_MAKE_FAST_ALLOCATED;
81public:
82    ~MutexBase();
83
84    void lock();
85    void unlock();
86#if ENABLE(ASSERT)
87    bool locked() { return m_mutex.m_recursionCount > 0; }
88#endif
89
90public:
91    PlatformMutex& impl() { return m_mutex; }
92
93protected:
94    MutexBase(bool recursive);
95
96    PlatformMutex m_mutex;
97};
98
99class WTF_EXPORT Mutex : public MutexBase {
100public:
101    Mutex() : MutexBase(false) { }
102    bool tryLock();
103};
104
105class WTF_EXPORT RecursiveMutex : public MutexBase {
106public:
107    RecursiveMutex() : MutexBase(true) { }
108    bool tryLock();
109};
110
111typedef Locker<MutexBase> MutexLocker;
112
113class MutexTryLocker {
114    WTF_MAKE_NONCOPYABLE(MutexTryLocker);
115public:
116    MutexTryLocker(Mutex& mutex) : m_mutex(mutex), m_locked(mutex.tryLock()) { }
117    ~MutexTryLocker()
118    {
119        if (m_locked)
120            m_mutex.unlock();
121    }
122
123    bool locked() const { return m_locked; }
124
125private:
126    Mutex& m_mutex;
127    bool m_locked;
128};
129
130class WTF_EXPORT ThreadCondition {
131    WTF_MAKE_NONCOPYABLE(ThreadCondition);
132public:
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
143private:
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).
150DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime);
151#endif
152
153} // namespace WTF
154
155using WTF::MutexBase;
156using WTF::Mutex;
157using WTF::RecursiveMutex;
158using WTF::MutexLocker;
159using WTF::MutexTryLocker;
160using WTF::ThreadCondition;
161
162#if OS(WIN)
163using WTF::absoluteTimeToWaitTimeoutInterval;
164#endif
165
166#endif // ThreadingPrimitives_h
167