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