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