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