blob: 5448d8a807152a258f654dd4de046023719f8ad7 [file] [log] [blame]
Howard Hinnant6185ace2013-09-21 01:49:28 +00001// -*- C++ -*-
2//===------------------------ shared_mutex --------------------------------===//
3//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnant6185ace2013-09-21 01:49:28 +00007//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_SHARED_MUTEX
11#define _LIBCPP_SHARED_MUTEX
12
13/*
14 shared_mutex synopsis
15
16// C++1y
17
18namespace std
19{
20
Marshall Clowac28c3d2015-06-30 14:04:14 +000021class shared_mutex // C++17
22{
23public:
24 shared_mutex();
25 ~shared_mutex();
26
27 shared_mutex(const shared_mutex&) = delete;
28 shared_mutex& operator=(const shared_mutex&) = delete;
29
30 // Exclusive ownership
31 void lock(); // blocking
32 bool try_lock();
33 void unlock();
34
35 // Shared ownership
36 void lock_shared(); // blocking
37 bool try_lock_shared();
38 void unlock_shared();
39
40 typedef implementation-defined native_handle_type; // See 30.2.3
41 native_handle_type native_handle(); // See 30.2.3
42};
43
David Majnemer10c8c362014-03-17 20:19:44 +000044class shared_timed_mutex
Howard Hinnant6185ace2013-09-21 01:49:28 +000045{
46public:
David Majnemer10c8c362014-03-17 20:19:44 +000047 shared_timed_mutex();
48 ~shared_timed_mutex();
Howard Hinnant6185ace2013-09-21 01:49:28 +000049
David Majnemer10c8c362014-03-17 20:19:44 +000050 shared_timed_mutex(const shared_timed_mutex&) = delete;
51 shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
Howard Hinnant6185ace2013-09-21 01:49:28 +000052
53 // Exclusive ownership
54 void lock(); // blocking
55 bool try_lock();
56 template <class Rep, class Period>
57 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
58 template <class Clock, class Duration>
59 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
60 void unlock();
61
62 // Shared ownership
63 void lock_shared(); // blocking
64 bool try_lock_shared();
65 template <class Rep, class Period>
66 bool
67 try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time);
68 template <class Clock, class Duration>
69 bool
70 try_lock_shared_until(const chrono::time_point<Clock, Duration>& abs_time);
71 void unlock_shared();
72};
73
74template <class Mutex>
75class shared_lock
76{
77public:
78 typedef Mutex mutex_type;
79
80 // Shared locking
81 shared_lock() noexcept;
82 explicit shared_lock(mutex_type& m); // blocking
83 shared_lock(mutex_type& m, defer_lock_t) noexcept;
84 shared_lock(mutex_type& m, try_to_lock_t);
85 shared_lock(mutex_type& m, adopt_lock_t);
86 template <class Clock, class Duration>
87 shared_lock(mutex_type& m,
88 const chrono::time_point<Clock, Duration>& abs_time);
89 template <class Rep, class Period>
90 shared_lock(mutex_type& m,
91 const chrono::duration<Rep, Period>& rel_time);
92 ~shared_lock();
93
94 shared_lock(shared_lock const&) = delete;
95 shared_lock& operator=(shared_lock const&) = delete;
96
97 shared_lock(shared_lock&& u) noexcept;
98 shared_lock& operator=(shared_lock&& u) noexcept;
99
100 void lock(); // blocking
101 bool try_lock();
102 template <class Rep, class Period>
103 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
104 template <class Clock, class Duration>
105 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
106 void unlock();
107
108 // Setters
109 void swap(shared_lock& u) noexcept;
110 mutex_type* release() noexcept;
111
112 // Getters
113 bool owns_lock() const noexcept;
114 explicit operator bool () const noexcept;
115 mutex_type* mutex() const noexcept;
116};
117
118template <class Mutex>
119 void swap(shared_lock<Mutex>& x, shared_lock<Mutex>& y) noexcept;
120
121} // std
122
123*/
124
125#include <__config>
Louis Dionne73912b22020-11-04 15:01:25 -0500126#include <__availability>
Marshall Clow0a1e7502018-09-12 19:41:40 +0000127#include <version>
Howard Hinnant6185ace2013-09-21 01:49:28 +0000128
Eric Fiselierf4433a32017-05-31 22:07:49 +0000129_LIBCPP_PUSH_MACROS
130#include <__undef_macros>
131
132
Louis Dionne5e0eadd2018-08-01 02:08:59 +0000133#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_LIBRARY)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000134
135#include <__mutex_base>
136
Howard Hinnant6185ace2013-09-21 01:49:28 +0000137#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
138#pragma GCC system_header
139#endif
140
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000141#ifdef _LIBCPP_HAS_NO_THREADS
142#error <shared_mutex> is not supported on this single threaded system
143#else // !_LIBCPP_HAS_NO_THREADS
144
Howard Hinnant6185ace2013-09-21 01:49:28 +0000145_LIBCPP_BEGIN_NAMESPACE_STD
146
Petr Hosek23e8a762018-11-09 23:32:25 +0000147struct _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("shared_mutex"))
148__shared_mutex_base
Howard Hinnant6185ace2013-09-21 01:49:28 +0000149{
150 mutex __mut_;
151 condition_variable __gate1_;
152 condition_variable __gate2_;
153 unsigned __state_;
154
155 static const unsigned __write_entered_ = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1);
156 static const unsigned __n_readers_ = ~__write_entered_;
Marshall Clowac28c3d2015-06-30 14:04:14 +0000157
158 __shared_mutex_base();
159 _LIBCPP_INLINE_VISIBILITY ~__shared_mutex_base() = default;
160
161 __shared_mutex_base(const __shared_mutex_base&) = delete;
162 __shared_mutex_base& operator=(const __shared_mutex_base&) = delete;
163
164 // Exclusive ownership
Petr Hosek23e8a762018-11-09 23:32:25 +0000165 void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); // blocking
166 bool try_lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true));
167 void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability());
Marshall Clowac28c3d2015-06-30 14:04:14 +0000168
169 // Shared ownership
Petr Hosek23e8a762018-11-09 23:32:25 +0000170 void lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_shared_capability()); // blocking
171 bool try_lock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_shared_capability(true));
172 void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_shared_capability());
Marshall Clowac28c3d2015-06-30 14:04:14 +0000173
174// typedef implementation-defined native_handle_type; // See 30.2.3
175// native_handle_type native_handle(); // See 30.2.3
176};
177
178
179#if _LIBCPP_STD_VER > 14
Mehdi Amini228053d2017-05-04 17:08:54 +0000180class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_mutex
Marshall Clowac28c3d2015-06-30 14:04:14 +0000181{
Marshall Clow580b6e62017-03-24 03:40:36 +0000182 __shared_mutex_base __base;
Marshall Clowac28c3d2015-06-30 14:04:14 +0000183public:
Eric Fiselier26654172017-05-08 01:31:50 +0000184 _LIBCPP_INLINE_VISIBILITY shared_mutex() : __base() {}
Marshall Clowac28c3d2015-06-30 14:04:14 +0000185 _LIBCPP_INLINE_VISIBILITY ~shared_mutex() = default;
186
187 shared_mutex(const shared_mutex&) = delete;
188 shared_mutex& operator=(const shared_mutex&) = delete;
189
190 // Exclusive ownership
191 _LIBCPP_INLINE_VISIBILITY void lock() { return __base.lock(); }
192 _LIBCPP_INLINE_VISIBILITY bool try_lock() { return __base.try_lock(); }
193 _LIBCPP_INLINE_VISIBILITY void unlock() { return __base.unlock(); }
194
195 // Shared ownership
196 _LIBCPP_INLINE_VISIBILITY void lock_shared() { return __base.lock_shared(); }
197 _LIBCPP_INLINE_VISIBILITY bool try_lock_shared() { return __base.try_lock_shared(); }
198 _LIBCPP_INLINE_VISIBILITY void unlock_shared() { return __base.unlock_shared(); }
199
200// typedef __shared_mutex_base::native_handle_type native_handle_type;
201// _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() { return __base::unlock_shared(); }
202};
203#endif
204
205
Mehdi Amini228053d2017-05-04 17:08:54 +0000206class _LIBCPP_TYPE_VIS _LIBCPP_AVAILABILITY_SHARED_MUTEX shared_timed_mutex
Marshall Clowac28c3d2015-06-30 14:04:14 +0000207{
Marshall Clow580b6e62017-03-24 03:40:36 +0000208 __shared_mutex_base __base;
Howard Hinnant6185ace2013-09-21 01:49:28 +0000209public:
David Majnemer10c8c362014-03-17 20:19:44 +0000210 shared_timed_mutex();
211 _LIBCPP_INLINE_VISIBILITY ~shared_timed_mutex() = default;
Howard Hinnant6185ace2013-09-21 01:49:28 +0000212
David Majnemer10c8c362014-03-17 20:19:44 +0000213 shared_timed_mutex(const shared_timed_mutex&) = delete;
214 shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
Howard Hinnant6185ace2013-09-21 01:49:28 +0000215
216 // Exclusive ownership
217 void lock();
218 bool try_lock();
219 template <class _Rep, class _Period>
220 _LIBCPP_INLINE_VISIBILITY
221 bool
222 try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time)
223 {
224 return try_lock_until(chrono::steady_clock::now() + __rel_time);
225 }
226 template <class _Clock, class _Duration>
Shoaib Meenai55f3a462017-03-02 03:22:18 +0000227 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
Howard Hinnant6185ace2013-09-21 01:49:28 +0000228 bool
229 try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
230 void unlock();
231
232 // Shared ownership
233 void lock_shared();
234 bool try_lock_shared();
235 template <class _Rep, class _Period>
236 _LIBCPP_INLINE_VISIBILITY
237 bool
238 try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rel_time)
239 {
240 return try_lock_shared_until(chrono::steady_clock::now() + __rel_time);
241 }
242 template <class _Clock, class _Duration>
Shoaib Meenai55f3a462017-03-02 03:22:18 +0000243 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
Howard Hinnant6185ace2013-09-21 01:49:28 +0000244 bool
245 try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time);
246 void unlock_shared();
247};
248
249template <class _Clock, class _Duration>
250bool
David Majnemer10c8c362014-03-17 20:19:44 +0000251shared_timed_mutex::try_lock_until(
Howard Hinnant6185ace2013-09-21 01:49:28 +0000252 const chrono::time_point<_Clock, _Duration>& __abs_time)
253{
Marshall Clowac28c3d2015-06-30 14:04:14 +0000254 unique_lock<mutex> __lk(__base.__mut_);
255 if (__base.__state_ & __base.__write_entered_)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000256 {
257 while (true)
258 {
Marshall Clowac28c3d2015-06-30 14:04:14 +0000259 cv_status __status = __base.__gate1_.wait_until(__lk, __abs_time);
260 if ((__base.__state_ & __base.__write_entered_) == 0)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000261 break;
262 if (__status == cv_status::timeout)
263 return false;
264 }
265 }
Marshall Clowac28c3d2015-06-30 14:04:14 +0000266 __base.__state_ |= __base.__write_entered_;
267 if (__base.__state_ & __base.__n_readers_)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000268 {
269 while (true)
270 {
Marshall Clowac28c3d2015-06-30 14:04:14 +0000271 cv_status __status = __base.__gate2_.wait_until(__lk, __abs_time);
272 if ((__base.__state_ & __base.__n_readers_) == 0)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000273 break;
274 if (__status == cv_status::timeout)
275 {
Marshall Clowac28c3d2015-06-30 14:04:14 +0000276 __base.__state_ &= ~__base.__write_entered_;
277 __base.__gate1_.notify_all();
Howard Hinnant6185ace2013-09-21 01:49:28 +0000278 return false;
279 }
280 }
281 }
282 return true;
283}
284
285template <class _Clock, class _Duration>
286bool
David Majnemer10c8c362014-03-17 20:19:44 +0000287shared_timed_mutex::try_lock_shared_until(
Howard Hinnant6185ace2013-09-21 01:49:28 +0000288 const chrono::time_point<_Clock, _Duration>& __abs_time)
289{
Marshall Clowac28c3d2015-06-30 14:04:14 +0000290 unique_lock<mutex> __lk(__base.__mut_);
291 if ((__base.__state_ & __base.__write_entered_) || (__base.__state_ & __base.__n_readers_) == __base.__n_readers_)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000292 {
293 while (true)
294 {
Marshall Clowac28c3d2015-06-30 14:04:14 +0000295 cv_status status = __base.__gate1_.wait_until(__lk, __abs_time);
296 if ((__base.__state_ & __base.__write_entered_) == 0 &&
297 (__base.__state_ & __base.__n_readers_) < __base.__n_readers_)
Howard Hinnant6185ace2013-09-21 01:49:28 +0000298 break;
299 if (status == cv_status::timeout)
300 return false;
301 }
302 }
Marshall Clowac28c3d2015-06-30 14:04:14 +0000303 unsigned __num_readers = (__base.__state_ & __base.__n_readers_) + 1;
304 __base.__state_ &= ~__base.__n_readers_;
305 __base.__state_ |= __num_readers;
Howard Hinnant6185ace2013-09-21 01:49:28 +0000306 return true;
307}
308
309template <class _Mutex>
310class shared_lock
311{
312public:
313 typedef _Mutex mutex_type;
314
315private:
316 mutex_type* __m_;
317 bool __owns_;
318
319public:
320 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000321 shared_lock() _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000322 : __m_(nullptr),
323 __owns_(false)
324 {}
325
326 _LIBCPP_INLINE_VISIBILITY
327 explicit shared_lock(mutex_type& __m)
Marshall Clow24ddc252016-04-13 17:02:23 +0000328 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000329 __owns_(true)
330 {__m_->lock_shared();}
331
332 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000333 shared_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT
Marshall Clow24ddc252016-04-13 17:02:23 +0000334 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000335 __owns_(false)
336 {}
337
338 _LIBCPP_INLINE_VISIBILITY
339 shared_lock(mutex_type& __m, try_to_lock_t)
Marshall Clow24ddc252016-04-13 17:02:23 +0000340 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000341 __owns_(__m.try_lock_shared())
342 {}
343
344 _LIBCPP_INLINE_VISIBILITY
345 shared_lock(mutex_type& __m, adopt_lock_t)
Marshall Clow24ddc252016-04-13 17:02:23 +0000346 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000347 __owns_(true)
348 {}
349
350 template <class _Clock, class _Duration>
351 _LIBCPP_INLINE_VISIBILITY
352 shared_lock(mutex_type& __m,
353 const chrono::time_point<_Clock, _Duration>& __abs_time)
Marshall Clow24ddc252016-04-13 17:02:23 +0000354 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000355 __owns_(__m.try_lock_shared_until(__abs_time))
356 {}
357
358 template <class _Rep, class _Period>
359 _LIBCPP_INLINE_VISIBILITY
360 shared_lock(mutex_type& __m,
361 const chrono::duration<_Rep, _Period>& __rel_time)
Marshall Clow24ddc252016-04-13 17:02:23 +0000362 : __m_(_VSTD::addressof(__m)),
Howard Hinnant6185ace2013-09-21 01:49:28 +0000363 __owns_(__m.try_lock_shared_for(__rel_time))
364 {}
365
366 _LIBCPP_INLINE_VISIBILITY
367 ~shared_lock()
368 {
369 if (__owns_)
370 __m_->unlock_shared();
371 }
372
373 shared_lock(shared_lock const&) = delete;
374 shared_lock& operator=(shared_lock const&) = delete;
375
376 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000377 shared_lock(shared_lock&& __u) _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000378 : __m_(__u.__m_),
379 __owns_(__u.__owns_)
380 {
381 __u.__m_ = nullptr;
382 __u.__owns_ = false;
383 }
384
385 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000386 shared_lock& operator=(shared_lock&& __u) _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000387 {
388 if (__owns_)
389 __m_->unlock_shared();
390 __m_ = nullptr;
391 __owns_ = false;
392 __m_ = __u.__m_;
393 __owns_ = __u.__owns_;
394 __u.__m_ = nullptr;
395 __u.__owns_ = false;
396 return *this;
397 }
398
399 void lock();
400 bool try_lock();
401 template <class Rep, class Period>
402 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
403 template <class Clock, class Duration>
404 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
405 void unlock();
406
407 // Setters
408 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000409 void swap(shared_lock& __u) _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000410 {
411 _VSTD::swap(__m_, __u.__m_);
412 _VSTD::swap(__owns_, __u.__owns_);
413 }
414
415 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000416 mutex_type* release() _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000417 {
418 mutex_type* __m = __m_;
419 __m_ = nullptr;
420 __owns_ = false;
421 return __m;
422 }
423
424 // Getters
425 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000426 bool owns_lock() const _NOEXCEPT {return __owns_;}
Howard Hinnant6185ace2013-09-21 01:49:28 +0000427
428 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000429 explicit operator bool () const _NOEXCEPT {return __owns_;}
Howard Hinnant6185ace2013-09-21 01:49:28 +0000430
431 _LIBCPP_INLINE_VISIBILITY
Marshall Clowdf4053a2014-08-25 14:53:16 +0000432 mutex_type* mutex() const _NOEXCEPT {return __m_;}
Howard Hinnant6185ace2013-09-21 01:49:28 +0000433};
434
435template <class _Mutex>
436void
437shared_lock<_Mutex>::lock()
438{
439 if (__m_ == nullptr)
440 __throw_system_error(EPERM, "shared_lock::lock: references null mutex");
441 if (__owns_)
442 __throw_system_error(EDEADLK, "shared_lock::lock: already locked");
443 __m_->lock_shared();
444 __owns_ = true;
445}
446
447template <class _Mutex>
448bool
449shared_lock<_Mutex>::try_lock()
450{
451 if (__m_ == nullptr)
452 __throw_system_error(EPERM, "shared_lock::try_lock: references null mutex");
453 if (__owns_)
454 __throw_system_error(EDEADLK, "shared_lock::try_lock: already locked");
455 __owns_ = __m_->try_lock_shared();
456 return __owns_;
457}
458
459template <class _Mutex>
460template <class _Rep, class _Period>
461bool
462shared_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d)
463{
464 if (__m_ == nullptr)
465 __throw_system_error(EPERM, "shared_lock::try_lock_for: references null mutex");
466 if (__owns_)
467 __throw_system_error(EDEADLK, "shared_lock::try_lock_for: already locked");
468 __owns_ = __m_->try_lock_shared_for(__d);
469 return __owns_;
470}
471
472template <class _Mutex>
473template <class _Clock, class _Duration>
474bool
475shared_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t)
476{
477 if (__m_ == nullptr)
478 __throw_system_error(EPERM, "shared_lock::try_lock_until: references null mutex");
479 if (__owns_)
480 __throw_system_error(EDEADLK, "shared_lock::try_lock_until: already locked");
481 __owns_ = __m_->try_lock_shared_until(__t);
482 return __owns_;
483}
484
485template <class _Mutex>
486void
487shared_lock<_Mutex>::unlock()
488{
489 if (!__owns_)
490 __throw_system_error(EPERM, "shared_lock::unlock: not locked");
491 __m_->unlock_shared();
492 __owns_ = false;
493}
494
495template <class _Mutex>
496inline _LIBCPP_INLINE_VISIBILITY
497void
Marshall Clowdf4053a2014-08-25 14:53:16 +0000498swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) _NOEXCEPT
Howard Hinnant6185ace2013-09-21 01:49:28 +0000499 {__x.swap(__y);}
500
501_LIBCPP_END_NAMESPACE_STD
502
Jonathan Roelofs39cb6bf2014-09-05 19:45:05 +0000503#endif // !_LIBCPP_HAS_NO_THREADS
504
Howard Hinnant6185ace2013-09-21 01:49:28 +0000505#endif // _LIBCPP_STD_VER > 11
506
Eric Fiselierf4433a32017-05-31 22:07:49 +0000507_LIBCPP_POP_MACROS
508
Howard Hinnant6185ace2013-09-21 01:49:28 +0000509#endif // _LIBCPP_SHARED_MUTEX