OLD | NEW |
1 // Copyright 2007 The RE2 Authors. All Rights Reserved. | 1 // Copyright 2007 The RE2 Authors. All Rights Reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 /* | 5 /* |
6 * A simple mutex wrapper, supporting locks and read-write locks. | 6 * A simple mutex wrapper, supporting locks and read-write locks. |
7 * You should assume the locks are *not* re-entrant. | 7 * You should assume the locks are *not* re-entrant. |
8 */ | 8 */ |
9 | 9 |
10 #ifndef RE2_UTIL_MUTEX_H_ | 10 #ifndef RE2_UTIL_MUTEX_H_ |
11 #define RE2_UTIL_MUTEX_H_ | 11 #define RE2_UTIL_MUTEX_H_ |
12 | 12 |
| 13 #include <stdlib.h> |
| 14 |
| 15 #if !defined(_WIN32) |
| 16 #include <unistd.h> // For POSIX options |
| 17 #endif |
| 18 |
13 namespace re2 { | 19 namespace re2 { |
14 | 20 |
15 #ifndef WIN32 | 21 #if !defined(_WIN32) |
16 #define HAVE_PTHREAD 1 | 22 // Possible values of POSIX options: |
17 #define HAVE_RWLOCK 1 | 23 // -1 means not supported, |
| 24 // 0 means maybe supported (query at runtime), |
| 25 // >0 means supported. |
| 26 # if defined(_POSIX_THREADS) && _POSIX_THREADS > 0 |
| 27 # define HAVE_PTHREAD 1 |
| 28 # else |
| 29 # define HAVE_PTHREAD 0 |
| 30 # endif |
| 31 # if defined(_POSIX_READER_WRITER_LOCKS) && _POSIX_READER_WRITER_LOCKS > 0 |
| 32 # define HAVE_RWLOCK 1 |
| 33 # else |
| 34 # define HAVE_RWLOCK 0 |
| 35 # endif |
| 36 #else |
| 37 # define HAVE_PTHREAD 0 |
| 38 # define HAVE_RWLOCK 0 |
18 #endif | 39 #endif |
19 | 40 |
20 #if defined(NO_THREADS) | 41 #if defined(NO_THREADS) |
21 typedef int MutexType; // to keep a lock-count | 42 typedef int MutexType; // to keep a lock-count |
22 #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) | 43 #elif HAVE_PTHREAD && HAVE_RWLOCK |
23 // Needed for pthread_rwlock_*. If it causes problems, you could take it | 44 // Needed for pthread_rwlock_*. If it causes problems, you could take it |
24 // out, but then you'd have to unset HAVE_RWLOCK (at least on linux -- it | 45 // out, but then you'd have to set HAVE_RWLOCK to 0 (at least on linux -- |
25 // *does* cause problems for FreeBSD, or MacOSX, but isn't needed | 46 // it *does* cause problems for FreeBSD, or MacOSX, but isn't needed |
26 // for locking there.) | 47 // for locking there.) |
27 # ifdef __linux__ | 48 # ifdef __linux__ |
28 # undef _XOPEN_SOURCE | 49 # undef _XOPEN_SOURCE |
29 # define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls | 50 # define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls |
30 # endif | 51 # endif |
31 # include <pthread.h> | 52 # include <pthread.h> |
32 typedef pthread_rwlock_t MutexType; | 53 typedef pthread_rwlock_t MutexType; |
33 #elif defined(HAVE_PTHREAD) | 54 #elif HAVE_PTHREAD |
34 # include <pthread.h> | 55 # include <pthread.h> |
35 typedef pthread_mutex_t MutexType; | 56 typedef pthread_mutex_t MutexType; |
36 #elif defined(WIN32) | 57 #elif defined(_WIN32) |
37 # ifndef WIN32_LEAN_AND_MEAN | 58 # ifndef WIN32_LEAN_AND_MEAN |
38 # define WIN32_LEAN_AND_MEAN // We only need minimal includes | 59 # define WIN32_LEAN_AND_MEAN // We only need minimal includes |
39 # endif | 60 # endif |
40 # ifdef GMUTEX_TRYLOCK | 61 # ifdef GMUTEX_TRYLOCK |
41 // We need Windows NT or later for TryEnterCriticalSection(). If you | 62 // We need Windows NT or later for TryEnterCriticalSection(). If you |
42 // don't need that functionality, you can remove these _WIN32_WINNT | 63 // don't need that functionality, you can remove these _WIN32_WINNT |
43 // lines, and change TryLock() to assert(0) or something. | 64 // lines, and change TryLock() to assert(0) or something. |
44 # ifndef _WIN32_WINNT | 65 # ifndef _WIN32_WINNT |
45 # define _WIN32_WINNT 0x0400 | 66 # define _WIN32_WINNT 0x0400 |
46 # endif | 67 # endif |
47 # endif | 68 # endif |
48 # include <windows.h> | 69 # include <windows.h> |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 #include <assert.h> | 118 #include <assert.h> |
98 | 119 |
99 Mutex::Mutex() : mutex_(0) { } | 120 Mutex::Mutex() : mutex_(0) { } |
100 Mutex::~Mutex() { assert(mutex_ == 0); } | 121 Mutex::~Mutex() { assert(mutex_ == 0); } |
101 void Mutex::Lock() { assert(--mutex_ == -1); } | 122 void Mutex::Lock() { assert(--mutex_ == -1); } |
102 void Mutex::Unlock() { assert(mutex_++ == -1); } | 123 void Mutex::Unlock() { assert(mutex_++ == -1); } |
103 bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } | 124 bool Mutex::TryLock() { if (mutex_) return false; Lock(); return true; } |
104 void Mutex::ReaderLock() { assert(++mutex_ > 0); } | 125 void Mutex::ReaderLock() { assert(++mutex_ > 0); } |
105 void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } | 126 void Mutex::ReaderUnlock() { assert(mutex_-- > 0); } |
106 | 127 |
107 #elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK) | 128 #elif HAVE_PTHREAD && HAVE_RWLOCK |
108 | 129 |
109 #include <stdlib.h> // for abort() | |
110 #define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0) | 130 #define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0) |
111 | 131 |
112 Mutex::Mutex() { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); } | 132 Mutex::Mutex() { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); } |
113 Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy(&mutex_)); } | 133 Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy(&mutex_)); } |
114 void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock(&mutex_)); } | 134 void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock(&mutex_)); } |
115 void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); } | 135 void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); } |
116 bool Mutex::TryLock() { return pthread_rwlock_trywrlock(&mutex_) == 0; } | 136 bool Mutex::TryLock() { return pthread_rwlock_trywrlock(&mutex_) == 0; } |
117 void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock(&mutex_)); } | 137 void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock(&mutex_)); } |
118 void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); } | 138 void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); } |
119 | 139 |
120 #undef SAFE_PTHREAD | 140 #undef SAFE_PTHREAD |
121 | 141 |
122 #elif defined(HAVE_PTHREAD) | 142 #elif HAVE_PTHREAD |
123 | 143 |
124 #include <stdlib.h> // for abort() | |
125 #define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0) | 144 #define SAFE_PTHREAD(fncall) do { if ((fncall) != 0) abort(); } while (0) |
126 | 145 |
127 Mutex::Mutex() { SAFE_PTHREAD(pthread_mutex_init(&mutex_, NULL)); } | 146 Mutex::Mutex() { SAFE_PTHREAD(pthread_mutex_init(&mutex_, NULL)); } |
128 Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy(&mutex_)); } | 147 Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy(&mutex_)); } |
129 void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock(&mutex_)); } | 148 void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock(&mutex_)); } |
130 void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock(&mutex_)); } | 149 void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock(&mutex_)); } |
131 bool Mutex::TryLock() { return pthread_mutex_trylock(&mutex_) == 0; } | 150 bool Mutex::TryLock() { return pthread_mutex_trylock(&mutex_) == 0; } |
132 void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks | 151 void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks |
133 void Mutex::ReaderUnlock() { Unlock(); } | 152 void Mutex::ReaderUnlock() { Unlock(); } |
134 #undef SAFE_PTHREAD | 153 #undef SAFE_PTHREAD |
135 | 154 |
136 #elif defined(WIN32) | 155 #elif defined(_WIN32) |
137 | 156 |
138 Mutex::Mutex() { InitializeCriticalSection(&mutex_); } | 157 Mutex::Mutex() { InitializeCriticalSection(&mutex_); } |
139 Mutex::~Mutex() { DeleteCriticalSection(&mutex_); } | 158 Mutex::~Mutex() { DeleteCriticalSection(&mutex_); } |
140 void Mutex::Lock() { EnterCriticalSection(&mutex_); } | 159 void Mutex::Lock() { EnterCriticalSection(&mutex_); } |
141 void Mutex::Unlock() { LeaveCriticalSection(&mutex_); } | 160 void Mutex::Unlock() { LeaveCriticalSection(&mutex_); } |
142 bool Mutex::TryLock() { return TryEnterCriticalSection(&mutex_) != 0; } | 161 bool Mutex::TryLock() { return TryEnterCriticalSection(&mutex_) != 0; } |
143 void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks | 162 void Mutex::ReaderLock() { Lock(); } // we don't have read-write locks |
144 void Mutex::ReaderUnlock() { Unlock(); } | 163 void Mutex::ReaderUnlock() { Unlock(); } |
145 | 164 |
146 #endif | 165 #endif |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 WriterMutexLock(const WriterMutexLock&); | 202 WriterMutexLock(const WriterMutexLock&); |
184 void operator=(const WriterMutexLock&); | 203 void operator=(const WriterMutexLock&); |
185 }; | 204 }; |
186 | 205 |
187 // Catch bug where variable name is omitted, e.g. MutexLock (&mu); | 206 // Catch bug where variable name is omitted, e.g. MutexLock (&mu); |
188 #define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) | 207 #define MutexLock(x) COMPILE_ASSERT(0, mutex_lock_decl_missing_var_name) |
189 #define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) | 208 #define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name) |
190 #define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) | 209 #define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name) |
191 | 210 |
192 // Provide safe way to declare and use global, linker-initialized mutex. Sigh. | 211 // Provide safe way to declare and use global, linker-initialized mutex. Sigh. |
193 #ifdef HAVE_PTHREAD | 212 #if HAVE_PTHREAD |
194 | 213 |
195 #define GLOBAL_MUTEX(name) \ | 214 #define GLOBAL_MUTEX(name) \ |
196 static pthread_mutex_t (name) = PTHREAD_MUTEX_INITIALIZER | 215 static pthread_mutex_t (name) = PTHREAD_MUTEX_INITIALIZER |
197 #define GLOBAL_MUTEX_LOCK(name) \ | 216 #define GLOBAL_MUTEX_LOCK(name) \ |
198 pthread_mutex_lock(&(name)) | 217 pthread_mutex_lock(&(name)) |
199 #define GLOBAL_MUTEX_UNLOCK(name) \ | 218 #define GLOBAL_MUTEX_UNLOCK(name) \ |
200 pthread_mutex_unlock(&(name)) | 219 pthread_mutex_unlock(&(name)) |
201 | 220 |
202 #else | 221 #else |
203 | 222 |
204 #define GLOBAL_MUTEX(name) \ | 223 #define GLOBAL_MUTEX(name) \ |
205 static Mutex name | 224 static Mutex name |
206 #define GLOBAL_MUTEX_LOCK(name) \ | 225 #define GLOBAL_MUTEX_LOCK(name) \ |
207 name.Lock() | 226 name.Lock() |
208 #define GLOBAL_MUTEX_UNLOCK(name) \ | 227 #define GLOBAL_MUTEX_UNLOCK(name) \ |
209 name.Unlock() | 228 name.Unlock() |
210 | 229 |
211 #endif | 230 #endif |
212 | 231 |
213 } // namespace re2 | 232 } // namespace re2 |
214 | 233 |
215 #endif /* #define RE2_UTIL_MUTEX_H_ */ | 234 #endif /* #define RE2_UTIL_MUTEX_H_ */ |
OLD | NEW |