| 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 |