1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// 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 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP___MUTEX_BASE 11#define _LIBCPP___MUTEX_BASE 12 13#include <__config> 14#include <chrono> 15#include <system_error> 16#include <__threading_support> 17 18#include <time.h> 19 20#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21#pragma GCC system_header 22#endif 23 24_LIBCPP_PUSH_MACROS 25#include <__undef_macros> 26 27 28_LIBCPP_BEGIN_NAMESPACE_STD 29 30#ifndef _LIBCPP_HAS_NO_THREADS 31 32#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION 33# ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 34# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) 35# else 36# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) 37# endif 38#endif // _LIBCPP_THREAD_SAFETY_ANNOTATION 39 40 41class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex 42{ 43 __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; 44 45public: 46 _LIBCPP_INLINE_VISIBILITY 47 _LIBCPP_CONSTEXPR mutex() = default; 48 49 mutex(const mutex&) = delete; 50 mutex& operator=(const mutex&) = delete; 51 52#if defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) 53 ~mutex() = default; 54#else 55 ~mutex() _NOEXCEPT; 56#endif 57 58 void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); 59 bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); 60 void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); 61 62 typedef __libcpp_mutex_t* native_handle_type; 63 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} 64}; 65 66static_assert(is_nothrow_default_constructible<mutex>::value, 67 "the default constructor for std::mutex must be nothrow"); 68 69struct _LIBCPP_TYPE_VIS defer_lock_t {}; 70struct _LIBCPP_TYPE_VIS try_to_lock_t {}; 71struct _LIBCPP_TYPE_VIS adopt_lock_t {}; 72 73#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) 74 75extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock; 76extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock; 77extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock; 78 79#else 80 81/* _LIBCPP_INLINE_VAR */ constexpr defer_lock_t defer_lock = defer_lock_t(); 82/* _LIBCPP_INLINE_VAR */ constexpr try_to_lock_t try_to_lock = try_to_lock_t(); 83/* _LIBCPP_INLINE_VAR */ constexpr adopt_lock_t adopt_lock = adopt_lock_t(); 84 85#endif 86 87template <class _Mutex> 88class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) 89lock_guard 90{ 91public: 92 typedef _Mutex mutex_type; 93 94private: 95 mutex_type& __m_; 96public: 97 98 _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY 99 explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) 100 : __m_(__m) {__m_.lock();} 101 102 _LIBCPP_NODISCARD_EXT _LIBCPP_INLINE_VISIBILITY 103 lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) 104 : __m_(__m) {} 105 _LIBCPP_INLINE_VISIBILITY 106 ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} 107 108private: 109 lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE; 110 lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE; 111}; 112 113template <class _Mutex> 114class _LIBCPP_TEMPLATE_VIS unique_lock 115{ 116public: 117 typedef _Mutex mutex_type; 118 119private: 120 mutex_type* __m_; 121 bool __owns_; 122 123public: 124 _LIBCPP_INLINE_VISIBILITY 125 unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 126 _LIBCPP_INLINE_VISIBILITY 127 explicit unique_lock(mutex_type& __m) 128 : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();} 129 _LIBCPP_INLINE_VISIBILITY 130 unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 131 : __m_(_VSTD::addressof(__m)), __owns_(false) {} 132 _LIBCPP_INLINE_VISIBILITY 133 unique_lock(mutex_type& __m, try_to_lock_t) 134 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {} 135 _LIBCPP_INLINE_VISIBILITY 136 unique_lock(mutex_type& __m, adopt_lock_t) 137 : __m_(_VSTD::addressof(__m)), __owns_(true) {} 138 template <class _Clock, class _Duration> 139 _LIBCPP_INLINE_VISIBILITY 140 unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) 141 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} 142 template <class _Rep, class _Period> 143 _LIBCPP_INLINE_VISIBILITY 144 unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) 145 : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} 146 _LIBCPP_INLINE_VISIBILITY 147 ~unique_lock() 148 { 149 if (__owns_) 150 __m_->unlock(); 151 } 152 153private: 154 unique_lock(unique_lock const&); // = delete; 155 unique_lock& operator=(unique_lock const&); // = delete; 156 157public: 158#ifndef _LIBCPP_CXX03_LANG 159 _LIBCPP_INLINE_VISIBILITY 160 unique_lock(unique_lock&& __u) _NOEXCEPT 161 : __m_(__u.__m_), __owns_(__u.__owns_) 162 {__u.__m_ = nullptr; __u.__owns_ = false;} 163 _LIBCPP_INLINE_VISIBILITY 164 unique_lock& operator=(unique_lock&& __u) _NOEXCEPT 165 { 166 if (__owns_) 167 __m_->unlock(); 168 __m_ = __u.__m_; 169 __owns_ = __u.__owns_; 170 __u.__m_ = nullptr; 171 __u.__owns_ = false; 172 return *this; 173 } 174 175#endif // _LIBCPP_CXX03_LANG 176 177 void lock(); 178 bool try_lock(); 179 180 template <class _Rep, class _Period> 181 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); 182 template <class _Clock, class _Duration> 183 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 184 185 void unlock(); 186 187 _LIBCPP_INLINE_VISIBILITY 188 void swap(unique_lock& __u) _NOEXCEPT 189 { 190 _VSTD::swap(__m_, __u.__m_); 191 _VSTD::swap(__owns_, __u.__owns_); 192 } 193 _LIBCPP_INLINE_VISIBILITY 194 mutex_type* release() _NOEXCEPT 195 { 196 mutex_type* __m = __m_; 197 __m_ = nullptr; 198 __owns_ = false; 199 return __m; 200 } 201 202 _LIBCPP_INLINE_VISIBILITY 203 bool owns_lock() const _NOEXCEPT {return __owns_;} 204 _LIBCPP_INLINE_VISIBILITY 205 _LIBCPP_EXPLICIT 206 operator bool () const _NOEXCEPT {return __owns_;} 207 _LIBCPP_INLINE_VISIBILITY 208 mutex_type* mutex() const _NOEXCEPT {return __m_;} 209}; 210 211template <class _Mutex> 212void 213unique_lock<_Mutex>::lock() 214{ 215 if (__m_ == nullptr) 216 __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); 217 if (__owns_) 218 __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); 219 __m_->lock(); 220 __owns_ = true; 221} 222 223template <class _Mutex> 224bool 225unique_lock<_Mutex>::try_lock() 226{ 227 if (__m_ == nullptr) 228 __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); 229 if (__owns_) 230 __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); 231 __owns_ = __m_->try_lock(); 232 return __owns_; 233} 234 235template <class _Mutex> 236template <class _Rep, class _Period> 237bool 238unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 239{ 240 if (__m_ == nullptr) 241 __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); 242 if (__owns_) 243 __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); 244 __owns_ = __m_->try_lock_for(__d); 245 return __owns_; 246} 247 248template <class _Mutex> 249template <class _Clock, class _Duration> 250bool 251unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 252{ 253 if (__m_ == nullptr) 254 __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); 255 if (__owns_) 256 __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); 257 __owns_ = __m_->try_lock_until(__t); 258 return __owns_; 259} 260 261template <class _Mutex> 262void 263unique_lock<_Mutex>::unlock() 264{ 265 if (!__owns_) 266 __throw_system_error(EPERM, "unique_lock::unlock: not locked"); 267 __m_->unlock(); 268 __owns_ = false; 269} 270 271template <class _Mutex> 272inline _LIBCPP_INLINE_VISIBILITY 273void 274swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT 275 {__x.swap(__y);} 276 277//enum class cv_status 278_LIBCPP_DECLARE_STRONG_ENUM(cv_status) 279{ 280 no_timeout, 281 timeout 282}; 283_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) 284 285class _LIBCPP_TYPE_VIS condition_variable 286{ 287 __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; 288public: 289 _LIBCPP_INLINE_VISIBILITY 290 _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; 291 292#ifdef _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION 293 ~condition_variable() = default; 294#else 295 ~condition_variable(); 296#endif 297 298 condition_variable(const condition_variable&) = delete; 299 condition_variable& operator=(const condition_variable&) = delete; 300 301 void notify_one() _NOEXCEPT; 302 void notify_all() _NOEXCEPT; 303 304 void wait(unique_lock<mutex>& __lk) _NOEXCEPT; 305 template <class _Predicate> 306 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 307 void wait(unique_lock<mutex>& __lk, _Predicate __pred); 308 309 template <class _Clock, class _Duration> 310 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 311 cv_status 312 wait_until(unique_lock<mutex>& __lk, 313 const chrono::time_point<_Clock, _Duration>& __t); 314 315 template <class _Clock, class _Duration, class _Predicate> 316 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 317 bool 318 wait_until(unique_lock<mutex>& __lk, 319 const chrono::time_point<_Clock, _Duration>& __t, 320 _Predicate __pred); 321 322 template <class _Rep, class _Period> 323 _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS 324 cv_status 325 wait_for(unique_lock<mutex>& __lk, 326 const chrono::duration<_Rep, _Period>& __d); 327 328 template <class _Rep, class _Period, class _Predicate> 329 bool 330 _LIBCPP_INLINE_VISIBILITY 331 wait_for(unique_lock<mutex>& __lk, 332 const chrono::duration<_Rep, _Period>& __d, 333 _Predicate __pred); 334 335 typedef __libcpp_condvar_t* native_handle_type; 336 _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} 337 338private: 339 void __do_timed_wait(unique_lock<mutex>& __lk, 340 chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT; 341#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 342 void __do_timed_wait(unique_lock<mutex>& __lk, 343 chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT; 344#endif 345 template <class _Clock> 346 void __do_timed_wait(unique_lock<mutex>& __lk, 347 chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; 348}; 349#endif // !_LIBCPP_HAS_NO_THREADS 350 351template <class _Rep, class _Period> 352inline _LIBCPP_INLINE_VISIBILITY 353typename enable_if 354< 355 is_floating_point<_Rep>::value, 356 chrono::nanoseconds 357>::type 358__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) 359{ 360 using namespace chrono; 361 using __ratio = ratio_divide<_Period, nano>; 362 using __ns_rep = nanoseconds::rep; 363 _Rep __result_float = __d.count() * __ratio::num / __ratio::den; 364 365 _Rep __result_max = numeric_limits<__ns_rep>::max(); 366 if (__result_float >= __result_max) { 367 return nanoseconds::max(); 368 } 369 370 _Rep __result_min = numeric_limits<__ns_rep>::min(); 371 if (__result_float <= __result_min) { 372 return nanoseconds::min(); 373 } 374 375 return nanoseconds(static_cast<__ns_rep>(__result_float)); 376} 377 378template <class _Rep, class _Period> 379inline _LIBCPP_INLINE_VISIBILITY 380typename enable_if 381< 382 !is_floating_point<_Rep>::value, 383 chrono::nanoseconds 384>::type 385__safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) 386{ 387 using namespace chrono; 388 if (__d.count() == 0) { 389 return nanoseconds(0); 390 } 391 392 using __ratio = ratio_divide<_Period, nano>; 393 using __ns_rep = nanoseconds::rep; 394 __ns_rep __result_max = std::numeric_limits<__ns_rep>::max(); 395 if (__d.count() > 0 && __d.count() > __result_max / __ratio::num) { 396 return nanoseconds::max(); 397 } 398 399 __ns_rep __result_min = std::numeric_limits<__ns_rep>::min(); 400 if (__d.count() < 0 && __d.count() < __result_min / __ratio::num) { 401 return nanoseconds::min(); 402 } 403 404 __ns_rep __result = __d.count() * __ratio::num / __ratio::den; 405 if (__result == 0) { 406 return nanoseconds(1); 407 } 408 409 return nanoseconds(__result); 410} 411 412#ifndef _LIBCPP_HAS_NO_THREADS 413template <class _Predicate> 414void 415condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) 416{ 417 while (!__pred()) 418 wait(__lk); 419} 420 421template <class _Clock, class _Duration> 422cv_status 423condition_variable::wait_until(unique_lock<mutex>& __lk, 424 const chrono::time_point<_Clock, _Duration>& __t) 425{ 426 using namespace chrono; 427 using __clock_tp_ns = time_point<_Clock, nanoseconds>; 428 429 typename _Clock::time_point __now = _Clock::now(); 430 if (__t <= __now) 431 return cv_status::timeout; 432 433 __clock_tp_ns __t_ns = __clock_tp_ns(__safe_nanosecond_cast(__t.time_since_epoch())); 434 435 __do_timed_wait(__lk, __t_ns); 436 return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; 437} 438 439template <class _Clock, class _Duration, class _Predicate> 440bool 441condition_variable::wait_until(unique_lock<mutex>& __lk, 442 const chrono::time_point<_Clock, _Duration>& __t, 443 _Predicate __pred) 444{ 445 while (!__pred()) 446 { 447 if (wait_until(__lk, __t) == cv_status::timeout) 448 return __pred(); 449 } 450 return true; 451} 452 453template <class _Rep, class _Period> 454cv_status 455condition_variable::wait_for(unique_lock<mutex>& __lk, 456 const chrono::duration<_Rep, _Period>& __d) 457{ 458 using namespace chrono; 459 if (__d <= __d.zero()) 460 return cv_status::timeout; 461 using __ns_rep = nanoseconds::rep; 462 steady_clock::time_point __c_now = steady_clock::now(); 463 464#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 465 using __clock_tp_ns = time_point<steady_clock, nanoseconds>; 466 __ns_rep __now_count_ns = __safe_nanosecond_cast(__c_now.time_since_epoch()).count(); 467#else 468 using __clock_tp_ns = time_point<system_clock, nanoseconds>; 469 __ns_rep __now_count_ns = __safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); 470#endif 471 472 __ns_rep __d_ns_count = __safe_nanosecond_cast(__d).count(); 473 474 if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { 475 __do_timed_wait(__lk, __clock_tp_ns::max()); 476 } else { 477 __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); 478 } 479 480 return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : 481 cv_status::timeout; 482} 483 484template <class _Rep, class _Period, class _Predicate> 485inline 486bool 487condition_variable::wait_for(unique_lock<mutex>& __lk, 488 const chrono::duration<_Rep, _Period>& __d, 489 _Predicate __pred) 490{ 491 return wait_until(__lk, chrono::steady_clock::now() + __d, 492 _VSTD::move(__pred)); 493} 494 495#if defined(_LIBCPP_HAS_COND_CLOCKWAIT) 496inline 497void 498condition_variable::__do_timed_wait(unique_lock<mutex>& __lk, 499 chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT 500{ 501 using namespace chrono; 502 if (!__lk.owns_lock()) 503 __throw_system_error(EPERM, 504 "condition_variable::timed wait: mutex not locked"); 505 nanoseconds __d = __tp.time_since_epoch(); 506 timespec __ts; 507 seconds __s = duration_cast<seconds>(__d); 508 using __ts_sec = decltype(__ts.tv_sec); 509 const __ts_sec __ts_sec_max = numeric_limits<__ts_sec>::max(); 510 if (__s.count() < __ts_sec_max) 511 { 512 __ts.tv_sec = static_cast<__ts_sec>(__s.count()); 513 __ts.tv_nsec = (__d - __s).count(); 514 } 515 else 516 { 517 __ts.tv_sec = __ts_sec_max; 518 __ts.tv_nsec = giga::num - 1; 519 } 520 int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts); 521 if (__ec != 0 && __ec != ETIMEDOUT) 522 __throw_system_error(__ec, "condition_variable timed_wait failed"); 523} 524#endif // _LIBCPP_HAS_COND_CLOCKWAIT 525 526template <class _Clock> 527inline 528void 529condition_variable::__do_timed_wait(unique_lock<mutex>& __lk, 530 chrono::time_point<_Clock, chrono::nanoseconds> __tp) _NOEXCEPT 531{ 532 wait_for(__lk, __tp - _Clock::now()); 533} 534 535#endif // !_LIBCPP_HAS_NO_THREADS 536 537_LIBCPP_END_NAMESPACE_STD 538 539_LIBCPP_POP_MACROS 540 541#endif // _LIBCPP___MUTEX_BASE 542