/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_ |