1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is dual licensed under the MIT and the University of Illinois Open 7 // Source Licenses. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 #ifndef _LIBCPP___MUTEX_BASE 12 #define _LIBCPP___MUTEX_BASE 13 14 #include <__config> 15 #include <chrono> 16 #include <system_error> 17 #include <__threading_support> 18 19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20 #pragma GCC system_header 21 #endif 22 23 _LIBCPP_BEGIN_NAMESPACE_STD 24 25 #ifndef _LIBCPP_HAS_NO_THREADS 26 27 #ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION 28 # ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 29 # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) 30 # else 31 # define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) 32 # endif 33 #endif // _LIBCPP_THREAD_SAFETY_ANNOTATION 34 35 class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex 36 { 37 #ifndef _LIBCPP_HAS_NO_CONSTEXPR 38 __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; 39 #else 40 __libcpp_mutex_t __m_; 41 #endif 42 43 public: 44 _LIBCPP_INLINE_VISIBILITY 45 #ifndef _LIBCPP_HAS_NO_CONSTEXPR 46 constexpr mutex() _NOEXCEPT = default; 47 #else 48 mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;} 49 #endif 50 ~mutex(); 51 52 private: 53 mutex(const mutex&);// = delete; 54 mutex& operator=(const mutex&);// = delete; 55 56 public: 57 void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); 58 bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); 59 void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); 60 61 typedef __libcpp_mutex_t* native_handle_type; 62 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} 63 }; 64 65 struct _LIBCPP_TYPE_VIS defer_lock_t {}; 66 struct _LIBCPP_TYPE_VIS try_to_lock_t {}; 67 struct _LIBCPP_TYPE_VIS adopt_lock_t {}; 68 69 #if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX) 70 71 extern const defer_lock_t defer_lock; 72 extern const try_to_lock_t try_to_lock; 73 extern const adopt_lock_t adopt_lock; 74 75 #else 76 77 constexpr defer_lock_t defer_lock = defer_lock_t(); 78 constexpr try_to_lock_t try_to_lock = try_to_lock_t(); 79 constexpr adopt_lock_t adopt_lock = adopt_lock_t(); 80 81 #endif 82 83 84 // Forward declare lock_guard as a variadic template even in C++03 to keep 85 // the mangling consistent between dialects. 86 #if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD) 87 template <class ..._Mutexes> 88 class _LIBCPP_TEMPLATE_VIS lock_guard; 89 #endif 90 91 template <class _Mutex> 92 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) 93 #if !defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD) 94 lock_guard 95 #else 96 lock_guard<_Mutex> 97 #endif 98 { 99 public: 100 typedef _Mutex mutex_type; 101 102 private: 103 mutex_type& __m_; 104 public: 105 106 _LIBCPP_INLINE_VISIBILITY 107 explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 108 : __m_(__m) {__m_.lock();} 109 _LIBCPP_INLINE_VISIBILITY 110 lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 111 : __m_(__m) {} 112 _LIBCPP_INLINE_VISIBILITY 113 ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} 114 115 private: 116 lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE; 117 lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE; 118 }; 119 120 template <class _Mutex> 121 class _LIBCPP_TEMPLATE_VIS unique_lock 122 { 123 public: 124 typedef _Mutex mutex_type; 125 126 private: 127 mutex_type* __m_; 128 bool __owns_; 129 130 public: 131 _LIBCPP_INLINE_VISIBILITY 132 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 133 _LIBCPP_INLINE_VISIBILITY 134 explicit unique_lock(mutex_type& __m) 135 : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();} 136 _LIBCPP_INLINE_VISIBILITY 137 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 138 : __m_(_VSTD::addressof(__m)), __owns_(false) {} 139 _LIBCPP_INLINE_VISIBILITY 140 unique_lock(mutex_type& __m, try_to_lock_t) 141 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {} 142 _LIBCPP_INLINE_VISIBILITY 143 unique_lock(mutex_type& __m, adopt_lock_t) 144 : __m_(_VSTD::addressof(__m)), __owns_(true) {} 145 template <class _Clock, class _Duration> 146 _LIBCPP_INLINE_VISIBILITY 147 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) 148 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} 149 template <class _Rep, class _Period> 150 _LIBCPP_INLINE_VISIBILITY 151 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) 152 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} 153 _LIBCPP_INLINE_VISIBILITY 154 ~unique_lock() 155 { 156 if (__owns_) 157 __m_->unlock(); 158 } 159 160 private: 161 unique_lock(unique_lock const&); // = delete; 162 unique_lock& operator=(unique_lock const&); // = delete; 163 164 public: 165 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 166 _LIBCPP_INLINE_VISIBILITY 167 unique_lock(unique_lock&& __u) _NOEXCEPT 168 : __m_(__u.__m_), __owns_(__u.__owns_) 169 {__u.__m_ = nullptr; __u.__owns_ = false;} 170 _LIBCPP_INLINE_VISIBILITY 171 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT 172 { 173 if (__owns_) 174 __m_->unlock(); 175 __m_ = __u.__m_; 176 __owns_ = __u.__owns_; 177 __u.__m_ = nullptr; 178 __u.__owns_ = false; 179 return *this; 180 } 181 182 #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 183 184 void lock(); 185 bool try_lock(); 186 187 template <class _Rep, class _Period> 188 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); 189 template <class _Clock, class _Duration> 190 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 191 192 void unlock(); 193 194 _LIBCPP_INLINE_VISIBILITY 195 void swap(unique_lock& __u) _NOEXCEPT 196 { 197 _VSTD::swap(__m_, __u.__m_); 198 _VSTD::swap(__owns_, __u.__owns_); 199 } 200 _LIBCPP_INLINE_VISIBILITY 201 mutex_type* release() _NOEXCEPT 202 { 203 mutex_type* __m = __m_; 204 __m_ = nullptr; 205 __owns_ = false; 206 return __m; 207 } 208 209 _LIBCPP_INLINE_VISIBILITY 210 bool owns_lock() const _NOEXCEPT {return __owns_;} 211 _LIBCPP_INLINE_VISIBILITY 212 _LIBCPP_EXPLICIT 213 operator bool () const _NOEXCEPT {return __owns_;} 214 _LIBCPP_INLINE_VISIBILITY 215 mutex_type* mutex() const _NOEXCEPT {return __m_;} 216 }; 217 218 template <class _Mutex> 219 void 220 unique_lock<_Mutex>::lock() 221 { 222 if (__m_ == nullptr) 223 __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); 224 if (__owns_) 225 __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); 226 __m_->lock(); 227 __owns_ = true; 228 } 229 230 template <class _Mutex> 231 bool 232 unique_lock<_Mutex>::try_lock() 233 { 234 if (__m_ == nullptr) 235 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); 236 if (__owns_) 237 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); 238 __owns_ = __m_->try_lock(); 239 return __owns_; 240 } 241 242 template <class _Mutex> 243 template <class _Rep, class _Period> 244 bool 245 unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 246 { 247 if (__m_ == nullptr) 248 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); 249 if (__owns_) 250 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); 251 __owns_ = __m_->try_lock_for(__d); 252 return __owns_; 253 } 254 255 template <class _Mutex> 256 template <class _Clock, class _Duration> 257 bool 258 unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 259 { 260 if (__m_ == nullptr) 261 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); 262 if (__owns_) 263 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); 264 __owns_ = __m_->try_lock_until(__t); 265 return __owns_; 266 } 267 268 template <class _Mutex> 269 void 270 unique_lock<_Mutex>::unlock() 271 { 272 if (!__owns_) 273 __throw_system_error(EPERM, "unique_lock::unlock: not locked"); 274 __m_->unlock(); 275 __owns_ = false; 276 } 277 278 template <class _Mutex> 279 inline _LIBCPP_INLINE_VISIBILITY 280 void 281 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT 282 {__x.swap(__y);} 283 284 //enum class cv_status 285 _LIBCPP_DECLARE_STRONG_ENUM(cv_status) 286 { 287 no_timeout, 288 timeout 289 }; 290 _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) 291 292 class _LIBCPP_TYPE_VIS condition_variable 293 { 294 #ifndef _LIBCPP_HAS_NO_CONSTEXPR 295 __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; 296 #else 297 __libcpp_condvar_t __cv_; 298 #endif 299 300 public: 301 _LIBCPP_INLINE_VISIBILITY 302 #ifndef _LIBCPP_HAS_NO_CONSTEXPR 303 constexpr condition_variable() _NOEXCEPT = default; 304 #else 305 condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;} 306 #endif 307 ~condition_variable(); 308 309 private: 310 condition_variable(const condition_variable&); // = delete; 311 condition_variable& operator=(const condition_variable&); // = delete; 312 313 public: 314 void notify_one() _NOEXCEPT; 315 void notify_all() _NOEXCEPT; 316 317 void wait(unique_lock<mutex>& __lk) _NOEXCEPT; 318 template <class _Predicate> 319 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 320 void wait(unique_lock<mutex>& __lk, _Predicate __pred); 321 322 template <class _Clock, class _Duration> 323 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 324 cv_status 325 wait_until(unique_lock<mutex>& __lk, 326 const chrono::time_point<_Clock, _Duration>& __t); 327 328 template <class _Clock, class _Duration, class _Predicate> 329 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 330 bool 331 wait_until(unique_lock<mutex>& __lk, 332 const chrono::time_point<_Clock, _Duration>& __t, 333 _Predicate __pred); 334 335 template <class _Rep, class _Period> 336 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 337 cv_status 338 wait_for(unique_lock<mutex>& __lk, 339 const chrono::duration<_Rep, _Period>& __d); 340 341 template <class _Rep, class _Period, class _Predicate> 342 bool 343 _LIBCPP_INLINE_VISIBILITY 344 wait_for(unique_lock<mutex>& __lk, 345 const chrono::duration<_Rep, _Period>& __d, 346 _Predicate __pred); 347 348 typedef __libcpp_condvar_t* native_handle_type; 349 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} 350 351 private: 352 void __do_timed_wait(unique_lock<mutex>& __lk, 353 chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT; 354 }; 355 #endif // !_LIBCPP_HAS_NO_THREADS 356 357 template <class _To, class _Rep, class _Period> 358 inline _LIBCPP_INLINE_VISIBILITY 359 typename enable_if 360 < 361 chrono::__is_duration<_To>::value, 362 _To 363 >::type 364 __ceil(chrono::duration<_Rep, _Period> __d) 365 { 366 using namespace chrono; 367 _To __r = duration_cast<_To>(__d); 368 if (__r < __d) 369 ++__r; 370 return __r; 371 } 372 373 #ifndef _LIBCPP_HAS_NO_THREADS 374 template <class _Predicate> 375 void 376 condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) 377 { 378 while (!__pred()) 379 wait(__lk); 380 } 381 382 template <class _Clock, class _Duration> 383 cv_status 384 condition_variable::wait_until(unique_lock<mutex>& __lk, 385 const chrono::time_point<_Clock, _Duration>& __t) 386 { 387 using namespace chrono; 388 wait_for(__lk, __t - _Clock::now()); 389 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; 390 } 391 392 template <class _Clock, class _Duration, class _Predicate> 393 bool 394 condition_variable::wait_until(unique_lock<mutex>& __lk, 395 const chrono::time_point<_Clock, _Duration>& __t, 396 _Predicate __pred) 397 { 398 while (!__pred()) 399 { 400 if (wait_until(__lk, __t) == cv_status::timeout) 401 return __pred(); 402 } 403 return true; 404 } 405 406 template <class _Rep, class _Period> 407 cv_status 408 condition_variable::wait_for(unique_lock<mutex>& __lk, 409 const chrono::duration<_Rep, _Period>& __d) 410 { 411 using namespace chrono; 412 if (__d <= __d.zero()) 413 return cv_status::timeout; 414 typedef time_point<system_clock, duration<long double, nano> > __sys_tpf; 415 typedef time_point<system_clock, nanoseconds> __sys_tpi; 416 __sys_tpf _Max = __sys_tpi::max(); 417 steady_clock::time_point __c_now = steady_clock::now(); 418 system_clock::time_point __s_now = system_clock::now(); 419 if (_Max - __d > __s_now) 420 __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d)); 421 else 422 __do_timed_wait(__lk, __sys_tpi::max()); 423 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : 424 cv_status::timeout; 425 } 426 427 template <class _Rep, class _Period, class _Predicate> 428 inline 429 bool 430 condition_variable::wait_for(unique_lock<mutex>& __lk, 431 const chrono::duration<_Rep, _Period>& __d, 432 _Predicate __pred) 433 { 434 return wait_until(__lk, chrono::steady_clock::now() + __d, 435 _VSTD::move(__pred)); 436 } 437 438 #endif // !_LIBCPP_HAS_NO_THREADS 439 440 _LIBCPP_END_NAMESPACE_STD 441 442 #endif // _LIBCPP___MUTEX_BASE 443