Coverage Report

Created: 2025-06-12 07:25

/src/duckdb/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
#ifdef RE2_NO_THREADS
14
#include <assert.h>
15
#define MUTEX_IS_LOCK_COUNTER
16
#else
17
#ifdef _WIN32
18
// Requires Windows Vista or Windows Server 2008 at minimum.
19
#include <windows.h>
20
#if defined(WINVER) && WINVER >= 0x0600
21
#define MUTEX_IS_WIN32_SRWLOCK
22
#endif
23
#else
24
#ifndef _POSIX_C_SOURCE
25
#define _POSIX_C_SOURCE 200809L
26
#endif
27
#include <unistd.h>
28
#if defined(_POSIX_READER_WRITER_LOCKS) && _POSIX_READER_WRITER_LOCKS > 0
29
#define MUTEX_IS_PTHREAD_RWLOCK
30
#endif
31
#endif
32
#endif
33
34
#if defined(MUTEX_IS_LOCK_COUNTER)
35
typedef int MutexType;
36
#elif defined(MUTEX_IS_WIN32_SRWLOCK)
37
typedef SRWLOCK MutexType;
38
#elif defined(MUTEX_IS_PTHREAD_RWLOCK)
39
#include <stdexcept>
40
#include <pthread.h>
41
#include <stdlib.h>
42
typedef pthread_rwlock_t MutexType;
43
#else
44
#include <shared_mutex>
45
typedef std::shared_mutex MutexType;
46
#endif
47
48
namespace duckdb_re2 {
49
50
class Mutex {
51
 public:
52
  inline Mutex();
53
  inline ~Mutex();
54
  inline void Lock();    // Block if needed until free then acquire exclusively
55
  inline void Unlock();  // Release a lock acquired via Lock()
56
  // Note that on systems that don't support read-write locks, these may
57
  // be implemented as synonyms to Lock() and Unlock().  So you can use
58
  // these for efficiency, but don't use them anyplace where being able
59
  // to do shared reads is necessary to avoid deadlock.
60
  inline void ReaderLock();   // Block until free or shared then acquire a share
61
  inline void ReaderUnlock(); // Release a read share of this Mutex
62
0
  inline void WriterLock() { Lock(); }     // Acquire an exclusive lock
63
0
  inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()
64
65
 private:
66
  MutexType mutex_;
67
68
  // Catch the error of writing Mutex when intending MutexLock.
69
  Mutex(Mutex *ignored);
70
71
  Mutex(const Mutex&) = delete;
72
  Mutex& operator=(const Mutex&) = delete;
73
};
74
75
#if defined(MUTEX_IS_LOCK_COUNTER)
76
77
Mutex::Mutex()             : mutex_(0) { }
78
Mutex::~Mutex()            { assert(mutex_ == 0); }
79
void Mutex::Lock()         { assert(--mutex_ == -1); }
80
void Mutex::Unlock()       { assert(mutex_++ == -1); }
81
void Mutex::ReaderLock()   { assert(++mutex_ > 0); }
82
void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
83
84
#elif defined(MUTEX_IS_WIN32_SRWLOCK)
85
86
Mutex::Mutex()             : mutex_(SRWLOCK_INIT) { }
87
Mutex::~Mutex()            { }
88
void Mutex::Lock()         { AcquireSRWLockExclusive(&mutex_); }
89
void Mutex::Unlock()       { ReleaseSRWLockExclusive(&mutex_); }
90
void Mutex::ReaderLock()   { AcquireSRWLockShared(&mutex_); }
91
void Mutex::ReaderUnlock() { ReleaseSRWLockShared(&mutex_); }
92
93
#elif defined(MUTEX_IS_PTHREAD_RWLOCK)
94
95
#define SAFE_PTHREAD(fncall)    \
96
36.3k
  do {                          \
97
36.3k
    if ((fncall) != 0) throw std::runtime_error("RE2 pthread failure"); \
98
36.3k
  } while (0);
99
100
9.44k
Mutex::Mutex()             { SAFE_PTHREAD(pthread_rwlock_init(&mutex_, NULL)); }
101
9.44k
Mutex::~Mutex()            { pthread_rwlock_destroy(&mutex_); }
102
8.95k
void Mutex::Lock()         { SAFE_PTHREAD(pthread_rwlock_wrlock(&mutex_)); }
103
8.95k
void Mutex::Unlock()       { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
104
4.47k
void Mutex::ReaderLock()   { SAFE_PTHREAD(pthread_rwlock_rdlock(&mutex_)); }
105
4.47k
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock(&mutex_)); }
106
107
#undef SAFE_PTHREAD
108
109
#else
110
111
Mutex::Mutex()             { }
112
Mutex::~Mutex()            { }
113
void Mutex::Lock()         { mutex_.lock(); }
114
void Mutex::Unlock()       { mutex_.unlock(); }
115
void Mutex::ReaderLock()   { mutex_.lock_shared(); }
116
void Mutex::ReaderUnlock() { mutex_.unlock_shared(); }
117
118
#endif
119
120
// --------------------------------------------------------------------------
121
// Some helper classes
122
123
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
124
class MutexLock {
125
 public:
126
8.95k
  explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
127
8.95k
  ~MutexLock() { mu_->Unlock(); }
128
 private:
129
  Mutex * const mu_;
130
131
  MutexLock(const MutexLock&) = delete;
132
  MutexLock& operator=(const MutexLock&) = delete;
133
};
134
135
// ReaderMutexLock and WriterMutexLock do the same, for rwlocks
136
class ReaderMutexLock {
137
 public:
138
0
  explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
139
0
  ~ReaderMutexLock() { mu_->ReaderUnlock(); }
140
 private:
141
  Mutex * const mu_;
142
143
  ReaderMutexLock(const ReaderMutexLock&) = delete;
144
  ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
145
};
146
147
class WriterMutexLock {
148
 public:
149
0
  explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
150
0
  ~WriterMutexLock() { mu_->WriterUnlock(); }
151
 private:
152
  Mutex * const mu_;
153
154
  WriterMutexLock(const WriterMutexLock&) = delete;
155
  WriterMutexLock& operator=(const WriterMutexLock&) = delete;
156
};
157
158
// Catch bug where variable name is omitted, e.g. MutexLock (&mu);
159
#define MutexLock(x) static_assert(false, "MutexLock declaration missing variable name")
160
#define ReaderMutexLock(x) static_assert(false, "ReaderMutexLock declaration missing variable name")
161
#define WriterMutexLock(x) static_assert(false, "WriterMutexLock declaration missing variable name")
162
163
}  // namespace re2
164
165
#endif  // UTIL_MUTEX_H_