mutex.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright 2007 The RE2 Authors. All Rights Reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. #ifndef UTIL_MUTEX_H_
  5. #define UTIL_MUTEX_H_
  6. /*
  7. * A simple mutex wrapper, supporting locks and read-write locks.
  8. * You should assume the locks are *not* re-entrant.
  9. */
  10. #ifdef _WIN32
  11. // Requires Windows Vista or Windows Server 2008 at minimum.
  12. #include <windows.h>
  13. #if defined(WINVER) && WINVER >= 0x0600
  14. #define MUTEX_IS_WIN32_SRWLOCK
  15. #endif
  16. #else
  17. #ifndef _POSIX_C_SOURCE
  18. #define _POSIX_C_SOURCE 200809L
  19. #endif
  20. #include <unistd.h>
  21. #if defined(_POSIX_READER_WRITER_LOCKS) && _POSIX_READER_WRITER_LOCKS > 0
  22. #define MUTEX_IS_PTHREAD_RWLOCK
  23. #endif
  24. #endif
  25. #if defined(MUTEX_IS_WIN32_SRWLOCK)
  26. typedef SRWLOCK MutexType;
  27. #elif defined(MUTEX_IS_PTHREAD_RWLOCK)
  28. #include <pthread.h>
  29. #include <stdlib.h>
  30. typedef pthread_rwlock_t MutexType;
  31. #else
  32. #include <mutex>
  33. typedef std::mutex MutexType;
  34. #endif
  35. namespace re2 {
  36. class Mutex {
  37. public:
  38. inline Mutex();
  39. inline ~Mutex();
  40. inline void Lock(); // Block if needed until free then acquire exclusively
  41. inline void Unlock(); // Release a lock acquired via Lock()
  42. // Note that on systems that don't support read-write locks, these may
  43. // be implemented as synonyms to Lock() and Unlock(). So you can use
  44. // these for efficiency, but don't use them anyplace where being able
  45. // to do shared reads is necessary to avoid deadlock.
  46. inline void ReaderLock(); // Block until free or shared then acquire a share
  47. inline void ReaderUnlock(); // Release a read share of this Mutex
  48. inline void WriterLock() { Lock(); } // Acquire an exclusive lock
  49. inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
  50. private:
  51. MutexType mutex_;
  52. // Catch the error of writing Mutex when intending MutexLock.
  53. Mutex(Mutex *ignored);
  54. Mutex(const Mutex&) = delete;
  55. Mutex& operator=(const Mutex&) = delete;
  56. };
  57. #if defined(MUTEX_IS_WIN32_SRWLOCK)
  58. Mutex::Mutex() : mutex_(SRWLOCK_INIT) { }
  59. Mutex::~Mutex() { }
  60. void Mutex::Lock() { AcquireSRWLockExclusive(&mutex_); }
  61. void Mutex::Unlock() { ReleaseSRWLockExclusive(&mutex_); }
  62. void Mutex::ReaderLock() { AcquireSRWLockShared(&mutex_); }
  63. void Mutex::ReaderUnlock() { ReleaseSRWLockShared(&mutex_); }
  64. #elif defined(MUTEX_IS_PTHREAD_RWLOCK)
  65. #define SAFE_PTHREAD(fncall) \
  66. do { \
  67. if ((fncall) != 0) abort(); \
  68. } while (0)
  69. Mutex::Mutex() { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); }
  70. Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy(&mutex_)); }
  71. void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock(&mutex_)); }
  72. void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
  73. void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock(&mutex_)); }
  74. void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
  75. #undef SAFE_PTHREAD
  76. #else
  77. Mutex::Mutex() { }
  78. Mutex::~Mutex() { }
  79. void Mutex::Lock() { mutex_.lock(); }
  80. void Mutex::Unlock() { mutex_.unlock(); }
  81. void Mutex::ReaderLock() { Lock(); } // C++11 doesn't have std::shared_mutex.
  82. void Mutex::ReaderUnlock() { Unlock(); }
  83. #endif
  84. // --------------------------------------------------------------------------
  85. // Some helper classes
  86. // MutexLock(mu) acquires mu when constructed and releases it when destroyed.
  87. class MutexLock {
  88. public:
  89. explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
  90. ~MutexLock() { mu_->Unlock(); }
  91. private:
  92. Mutex * const mu_;
  93. MutexLock(const MutexLock&) = delete;
  94. MutexLock& operator=(const MutexLock&) = delete;
  95. };
  96. // ReaderMutexLock and WriterMutexLock do the same, for rwlocks
  97. class ReaderMutexLock {
  98. public:
  99. explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
  100. ~ReaderMutexLock() { mu_->ReaderUnlock(); }
  101. private:
  102. Mutex * const mu_;
  103. ReaderMutexLock(const ReaderMutexLock&) = delete;
  104. ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
  105. };
  106. class WriterMutexLock {
  107. public:
  108. explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
  109. ~WriterMutexLock() { mu_->WriterUnlock(); }
  110. private:
  111. Mutex * const mu_;
  112. WriterMutexLock(const WriterMutexLock&) = delete;
  113. WriterMutexLock& operator=(const WriterMutexLock&) = delete;
  114. };
  115. // Catch bug where variable name is omitted, e.g. MutexLock (&mu);
  116. #define MutexLock(x) static_assert(false, "MutexLock declaration missing variable name")
  117. #define ReaderMutexLock(x) static_assert(false, "ReaderMutexLock declaration missing variable name")
  118. #define WriterMutexLock(x) static_assert(false, "WriterMutexLock declaration missing variable name")
  119. } // namespace re2
  120. #endif // UTIL_MUTEX_H_