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