1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___MUTEX_UNIQUE_LOCK_H 10 #define _LIBCPP___MUTEX_UNIQUE_LOCK_H 11 12 #include <__chrono/duration.h> 13 #include <__chrono/time_point.h> 14 #include <__config> 15 #include <__memory/addressof.h> 16 #include <__mutex/tag_types.h> 17 #include <__system_error/throw_system_error.h> 18 #include <__utility/swap.h> 19 #include <cerrno> 20 21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 22 # pragma GCC system_header 23 #endif 24 25 _LIBCPP_BEGIN_NAMESPACE_STD 26 27 template <class _Mutex> 28 class _LIBCPP_TEMPLATE_VIS unique_lock { 29 public: 30 typedef _Mutex mutex_type; 31 32 private: 33 mutex_type* __m_; 34 bool __owns_; 35 36 public: 37 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 38 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI explicit unique_lock(mutex_type& __m) 39 : __m_(std::addressof(__m)), __owns_(true) { 40 __m_->lock(); 41 } 42 43 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 44 : __m_(std::addressof(__m)), 45 __owns_(false) {} 46 47 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, try_to_lock_t) 48 : __m_(std::addressof(__m)), __owns_(__m.try_lock()) {} 49 50 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, adopt_lock_t) 51 : __m_(std::addressof(__m)), __owns_(true) {} 52 53 template <class _Clock, class _Duration> 54 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) 55 : __m_(std::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} 56 57 template <class _Rep, class _Period> 58 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) 59 : __m_(std::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} 60 61 _LIBCPP_HIDE_FROM_ABI ~unique_lock() { 62 if (__owns_) 63 __m_->unlock(); 64 } 65 66 unique_lock(unique_lock const&) = delete; 67 unique_lock& operator=(unique_lock const&) = delete; 68 69 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI unique_lock(unique_lock&& __u) _NOEXCEPT 70 : __m_(__u.__m_), 71 __owns_(__u.__owns_) { 72 __u.__m_ = nullptr; 73 __u.__owns_ = false; 74 } 75 76 _LIBCPP_HIDE_FROM_ABI unique_lock& operator=(unique_lock&& __u) _NOEXCEPT { 77 if (__owns_) 78 __m_->unlock(); 79 80 __m_ = __u.__m_; 81 __owns_ = __u.__owns_; 82 __u.__m_ = nullptr; 83 __u.__owns_ = false; 84 return *this; 85 } 86 87 _LIBCPP_HIDE_FROM_ABI void lock(); 88 _LIBCPP_HIDE_FROM_ABI bool try_lock(); 89 90 template <class _Rep, class _Period> 91 _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); 92 93 template <class _Clock, class _Duration> 94 _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 95 96 _LIBCPP_HIDE_FROM_ABI void unlock(); 97 98 _LIBCPP_HIDE_FROM_ABI void swap(unique_lock& __u) _NOEXCEPT { 99 std::swap(__m_, __u.__m_); 100 std::swap(__owns_, __u.__owns_); 101 } 102 103 _LIBCPP_HIDE_FROM_ABI mutex_type* release() _NOEXCEPT { 104 mutex_type* __m = __m_; 105 __m_ = nullptr; 106 __owns_ = false; 107 return __m; 108 } 109 110 _LIBCPP_HIDE_FROM_ABI bool owns_lock() const _NOEXCEPT { return __owns_; } 111 _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __owns_; } 112 _LIBCPP_HIDE_FROM_ABI mutex_type* mutex() const _NOEXCEPT { return __m_; } 113 }; 114 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(unique_lock); 115 116 template <class _Mutex> 117 _LIBCPP_HIDE_FROM_ABI void unique_lock<_Mutex>::lock() { 118 if (__m_ == nullptr) 119 __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); 120 if (__owns_) 121 __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); 122 __m_->lock(); 123 __owns_ = true; 124 } 125 126 template <class _Mutex> 127 _LIBCPP_HIDE_FROM_ABI bool unique_lock<_Mutex>::try_lock() { 128 if (__m_ == nullptr) 129 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); 130 if (__owns_) 131 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); 132 __owns_ = __m_->try_lock(); 133 return __owns_; 134 } 135 136 template <class _Mutex> 137 template <class _Rep, class _Period> 138 _LIBCPP_HIDE_FROM_ABI bool unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) { 139 if (__m_ == nullptr) 140 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); 141 if (__owns_) 142 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); 143 __owns_ = __m_->try_lock_for(__d); 144 return __owns_; 145 } 146 147 template <class _Mutex> 148 template <class _Clock, class _Duration> 149 _LIBCPP_HIDE_FROM_ABI bool unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { 150 if (__m_ == nullptr) 151 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); 152 if (__owns_) 153 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); 154 __owns_ = __m_->try_lock_until(__t); 155 return __owns_; 156 } 157 158 template <class _Mutex> 159 _LIBCPP_HIDE_FROM_ABI void unique_lock<_Mutex>::unlock() { 160 if (!__owns_) 161 __throw_system_error(EPERM, "unique_lock::unlock: not locked"); 162 __m_->unlock(); 163 __owns_ = false; 164 } 165 166 template <class _Mutex> 167 inline _LIBCPP_HIDE_FROM_ABI void swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT { 168 __x.swap(__y); 169 } 170 171 _LIBCPP_END_NAMESPACE_STD 172 173 #endif // _LIBCPP___MUTEX_UNIQUE_LOCK_H 174