Coverage Report

Created: 2024-09-08 06:18

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