Coverage Report

Created: 2023-03-26 07:54

/src/LPM/external.protobuf/include/google/protobuf/stubs/mutex.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2006, Google Inc.
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
6
// met:
7
//
8
//     * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
//     * Redistributions in binary form must reproduce the above
11
// copyright notice, this list of conditions and the following disclaimer
12
// in the documentation and/or other materials provided with the
13
// distribution.
14
//     * Neither the name of Google Inc. nor the names of its
15
// contributors may be used to endorse or promote products derived from
16
// this software without specific prior written permission.
17
//
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
#ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_
31
#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_
32
33
#include <mutex>
34
35
#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
36
37
#include <windows.h>
38
39
// GetMessage conflicts with GeneratedMessageReflection::GetMessage().
40
#ifdef GetMessage
41
#undef GetMessage
42
#endif
43
44
#endif
45
46
#include <google/protobuf/stubs/macros.h>
47
48
// Define thread-safety annotations for use below, if we are building with
49
// Clang.
50
#if defined(__clang__) && !defined(SWIG)
51
#define GOOGLE_PROTOBUF_ACQUIRE(...) \
52
  __attribute__((acquire_capability(__VA_ARGS__)))
53
#define GOOGLE_PROTOBUF_RELEASE(...) \
54
  __attribute__((release_capability(__VA_ARGS__)))
55
#define GOOGLE_PROTOBUF_SCOPED_CAPABILITY __attribute__((scoped_lockable))
56
#define GOOGLE_PROTOBUF_CAPABILITY(x) __attribute__((capability(x)))
57
#else
58
#define GOOGLE_PROTOBUF_ACQUIRE(...)
59
#define GOOGLE_PROTOBUF_RELEASE(...)
60
#define GOOGLE_PROTOBUF_SCOPED_CAPABILITY
61
#define GOOGLE_PROTOBUF_CAPABILITY(x)
62
#endif
63
64
#include <google/protobuf/port_def.inc>
65
66
// ===================================================================
67
// emulates google3/base/mutex.h
68
namespace google {
69
namespace protobuf {
70
namespace internal {
71
72
#define GOOGLE_PROTOBUF_LINKER_INITIALIZED
73
74
#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
75
76
// This class is a lightweight replacement for std::mutex on Windows platforms.
77
// std::mutex does not work on Windows XP SP2 with the latest VC++ libraries,
78
// because it utilizes the Concurrency Runtime that is only supported on Windows
79
// XP SP3 and above.
80
class PROTOBUF_EXPORT CriticalSectionLock {
81
 public:
82
  CriticalSectionLock() { InitializeCriticalSection(&critical_section_); }
83
  ~CriticalSectionLock() { DeleteCriticalSection(&critical_section_); }
84
  void lock() { EnterCriticalSection(&critical_section_); }
85
  void unlock() { LeaveCriticalSection(&critical_section_); }
86
87
 private:
88
  CRITICAL_SECTION critical_section_;
89
90
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CriticalSectionLock);
91
};
92
93
#endif
94
95
// In MSVC std::mutex does not have a constexpr constructor.
96
// This wrapper makes the constructor constexpr.
97
template <typename T>
98
class CallOnceInitializedMutex {
99
 public:
100
  constexpr CallOnceInitializedMutex() : flag_{}, buf_{} {}
101
  ~CallOnceInitializedMutex() { get().~T(); }
102
103
  void lock() { get().lock(); }
104
  void unlock() { get().unlock(); }
105
106
 private:
107
  T& get() {
108
    std::call_once(flag_, [&] { ::new (static_cast<void*>(&buf_)) T(); });
109
    return reinterpret_cast<T&>(buf_);
110
  }
111
112
  std::once_flag flag_;
113
  alignas(T) char buf_[sizeof(T)];
114
};
115
116
// Mutex is a natural type to wrap. As both google and other organization have
117
// specialized mutexes. gRPC also provides an injection mechanism for custom
118
// mutexes.
119
class GOOGLE_PROTOBUF_CAPABILITY("mutex") PROTOBUF_EXPORT WrappedMutex {
120
 public:
121
#if defined(__QNX__)
122
  constexpr WrappedMutex() = default;
123
#else
124
0
  constexpr WrappedMutex() {}
125
#endif
126
0
  void Lock() GOOGLE_PROTOBUF_ACQUIRE() { mu_.lock(); }
127
0
  void Unlock() GOOGLE_PROTOBUF_RELEASE() { mu_.unlock(); }
128
  // Crash if this Mutex is not held exclusively by this thread.
129
  // May fail to crash when it should; will never crash when it should not.
130
0
  void AssertHeld() const {}
131
132
 private:
133
#if defined(GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP)
134
  CallOnceInitializedMutex<CriticalSectionLock> mu_{};
135
#elif defined(_WIN32)
136
  CallOnceInitializedMutex<std::mutex> mu_{};
137
#else
138
  std::mutex mu_{};
139
#endif
140
};
141
142
using Mutex = WrappedMutex;
143
144
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
145
class GOOGLE_PROTOBUF_SCOPED_CAPABILITY PROTOBUF_EXPORT MutexLock {
146
 public:
147
0
  explicit MutexLock(Mutex* mu) GOOGLE_PROTOBUF_ACQUIRE(mu) : mu_(mu) {
148
0
    this->mu_->Lock();
149
0
  }
150
0
  ~MutexLock() GOOGLE_PROTOBUF_RELEASE() { this->mu_->Unlock(); }
151
152
 private:
153
  Mutex *const mu_;
154
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock);
155
};
156
157
// TODO(kenton):  Implement these?  Hard to implement portably.
158
typedef MutexLock ReaderMutexLock;
159
typedef MutexLock WriterMutexLock;
160
161
// MutexLockMaybe is like MutexLock, but is a no-op when mu is nullptr.
162
class PROTOBUF_EXPORT MutexLockMaybe {
163
 public:
164
  explicit MutexLockMaybe(Mutex *mu) :
165
0
    mu_(mu) { if (this->mu_ != nullptr) { this->mu_->Lock(); } }
166
0
  ~MutexLockMaybe() { if (this->mu_ != nullptr) { this->mu_->Unlock(); } }
167
 private:
168
  Mutex *const mu_;
169
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
170
};
171
172
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
173
template<typename T>
174
class ThreadLocalStorage {
175
 public:
176
  ThreadLocalStorage() {
177
    pthread_key_create(&key_, &ThreadLocalStorage::Delete);
178
  }
179
  ~ThreadLocalStorage() {
180
    pthread_key_delete(key_);
181
  }
182
  T* Get() {
183
    T* result = static_cast<T*>(pthread_getspecific(key_));
184
    if (result == nullptr) {
185
      result = new T();
186
      pthread_setspecific(key_, result);
187
    }
188
    return result;
189
  }
190
 private:
191
  static void Delete(void* value) {
192
    delete static_cast<T*>(value);
193
  }
194
  pthread_key_t key_;
195
196
  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
197
};
198
#endif
199
200
}  // namespace internal
201
202
// We made these internal so that they would show up as such in the docs,
203
// but we don't want to stick "internal::" in front of them everywhere.
204
using internal::Mutex;
205
using internal::MutexLock;
206
using internal::ReaderMutexLock;
207
using internal::WriterMutexLock;
208
using internal::MutexLockMaybe;
209
210
}  // namespace protobuf
211
}  // namespace google
212
213
#undef GOOGLE_PROTOBUF_ACQUIRE
214
#undef GOOGLE_PROTOBUF_RELEASE
215
216
#include <google/protobuf/port_undef.inc>
217
218
#endif  // GOOGLE_PROTOBUF_STUBS_MUTEX_H_