__mutex_base revision 278724
1227825Stheraven// -*- C++ -*- 2227825Stheraven//===----------------------------------------------------------------------===// 3227825Stheraven// 4227825Stheraven// The LLVM Compiler Infrastructure 5227825Stheraven// 6227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 7227825Stheraven// Source Licenses. See LICENSE.TXT for details. 8227825Stheraven// 9227825Stheraven//===----------------------------------------------------------------------===// 10227825Stheraven 11227825Stheraven#ifndef _LIBCPP___MUTEX_BASE 12227825Stheraven#define _LIBCPP___MUTEX_BASE 13227825Stheraven 14227825Stheraven#include <__config> 15227825Stheraven#include <chrono> 16227825Stheraven#include <system_error> 17227825Stheraven#include <pthread.h> 18227825Stheraven 19227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20227825Stheraven#pragma GCC system_header 21227825Stheraven#endif 22227825Stheraven 23227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 24227825Stheraven 25278724Sdim#ifndef _LIBCPP_HAS_NO_THREADS 26278724Sdim 27249998Sdimclass _LIBCPP_TYPE_VIS mutex 28227825Stheraven{ 29227825Stheraven pthread_mutex_t __m_; 30227825Stheraven 31227825Stheravenpublic: 32227825Stheraven _LIBCPP_INLINE_VISIBILITY 33241903Sdim#ifndef _LIBCPP_HAS_NO_CONSTEXPR 34241903Sdim constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {} 35241903Sdim#else 36241903Sdim mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;} 37241903Sdim#endif 38227825Stheraven ~mutex(); 39227825Stheraven 40227825Stheravenprivate: 41227825Stheraven mutex(const mutex&);// = delete; 42227825Stheraven mutex& operator=(const mutex&);// = delete; 43227825Stheraven 44227825Stheravenpublic: 45227825Stheraven void lock(); 46241903Sdim bool try_lock() _NOEXCEPT; 47241903Sdim void unlock() _NOEXCEPT; 48227825Stheraven 49227825Stheraven typedef pthread_mutex_t* native_handle_type; 50227825Stheraven _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} 51227825Stheraven}; 52227825Stheraven 53249998Sdimstruct _LIBCPP_TYPE_VIS defer_lock_t {}; 54249998Sdimstruct _LIBCPP_TYPE_VIS try_to_lock_t {}; 55249998Sdimstruct _LIBCPP_TYPE_VIS adopt_lock_t {}; 56227825Stheraven 57241903Sdim#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX) 58227825Stheraven 59241903Sdimextern const defer_lock_t defer_lock; 60241903Sdimextern const try_to_lock_t try_to_lock; 61241903Sdimextern const adopt_lock_t adopt_lock; 62227825Stheraven 63241903Sdim#else 64227825Stheraven 65241903Sdimconstexpr defer_lock_t defer_lock = defer_lock_t(); 66241903Sdimconstexpr try_to_lock_t try_to_lock = try_to_lock_t(); 67241903Sdimconstexpr adopt_lock_t adopt_lock = adopt_lock_t(); 68241903Sdim 69241903Sdim#endif 70241903Sdim 71227825Stheraventemplate <class _Mutex> 72262801Sdimclass _LIBCPP_TYPE_VIS_ONLY lock_guard 73227825Stheraven{ 74227825Stheravenpublic: 75227825Stheraven typedef _Mutex mutex_type; 76227825Stheraven 77227825Stheravenprivate: 78227825Stheraven mutex_type& __m_; 79227825Stheravenpublic: 80227825Stheraven 81227825Stheraven _LIBCPP_INLINE_VISIBILITY 82227825Stheraven explicit lock_guard(mutex_type& __m) 83227825Stheraven : __m_(__m) {__m_.lock();} 84227825Stheraven _LIBCPP_INLINE_VISIBILITY 85227825Stheraven lock_guard(mutex_type& __m, adopt_lock_t) 86227825Stheraven : __m_(__m) {} 87227825Stheraven _LIBCPP_INLINE_VISIBILITY 88227825Stheraven ~lock_guard() {__m_.unlock();} 89227825Stheraven 90227825Stheravenprivate: 91227825Stheraven lock_guard(lock_guard const&);// = delete; 92227825Stheraven lock_guard& operator=(lock_guard const&);// = delete; 93227825Stheraven}; 94227825Stheraven 95227825Stheraventemplate <class _Mutex> 96262801Sdimclass _LIBCPP_TYPE_VIS_ONLY unique_lock 97227825Stheraven{ 98227825Stheravenpublic: 99227825Stheraven typedef _Mutex mutex_type; 100227825Stheraven 101227825Stheravenprivate: 102227825Stheraven mutex_type* __m_; 103227825Stheraven bool __owns_; 104227825Stheraven 105227825Stheravenpublic: 106227825Stheraven _LIBCPP_INLINE_VISIBILITY 107241903Sdim unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 108227825Stheraven _LIBCPP_INLINE_VISIBILITY 109227825Stheraven explicit unique_lock(mutex_type& __m) 110227825Stheraven : __m_(&__m), __owns_(true) {__m_->lock();} 111227825Stheraven _LIBCPP_INLINE_VISIBILITY 112241903Sdim unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 113227825Stheraven : __m_(&__m), __owns_(false) {} 114227825Stheraven _LIBCPP_INLINE_VISIBILITY 115227825Stheraven unique_lock(mutex_type& __m, try_to_lock_t) 116227825Stheraven : __m_(&__m), __owns_(__m.try_lock()) {} 117227825Stheraven _LIBCPP_INLINE_VISIBILITY 118227825Stheraven unique_lock(mutex_type& __m, adopt_lock_t) 119227825Stheraven : __m_(&__m), __owns_(true) {} 120227825Stheraven template <class _Clock, class _Duration> 121227825Stheraven _LIBCPP_INLINE_VISIBILITY 122227825Stheraven unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) 123227825Stheraven : __m_(&__m), __owns_(__m.try_lock_until(__t)) {} 124227825Stheraven template <class _Rep, class _Period> 125227825Stheraven _LIBCPP_INLINE_VISIBILITY 126227825Stheraven unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) 127227825Stheraven : __m_(&__m), __owns_(__m.try_lock_for(__d)) {} 128227825Stheraven _LIBCPP_INLINE_VISIBILITY 129227825Stheraven ~unique_lock() 130227825Stheraven { 131227825Stheraven if (__owns_) 132227825Stheraven __m_->unlock(); 133227825Stheraven } 134227825Stheraven 135227825Stheravenprivate: 136227825Stheraven unique_lock(unique_lock const&); // = delete; 137227825Stheraven unique_lock& operator=(unique_lock const&); // = delete; 138227825Stheraven 139227825Stheravenpublic: 140227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 141227825Stheraven _LIBCPP_INLINE_VISIBILITY 142241903Sdim unique_lock(unique_lock&& __u) _NOEXCEPT 143227825Stheraven : __m_(__u.__m_), __owns_(__u.__owns_) 144227825Stheraven {__u.__m_ = nullptr; __u.__owns_ = false;} 145227825Stheraven _LIBCPP_INLINE_VISIBILITY 146241903Sdim unique_lock& operator=(unique_lock&& __u) _NOEXCEPT 147227825Stheraven { 148227825Stheraven if (__owns_) 149227825Stheraven __m_->unlock(); 150227825Stheraven __m_ = __u.__m_; 151227825Stheraven __owns_ = __u.__owns_; 152227825Stheraven __u.__m_ = nullptr; 153227825Stheraven __u.__owns_ = false; 154227825Stheraven return *this; 155227825Stheraven } 156227825Stheraven 157227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 158227825Stheraven 159227825Stheraven void lock(); 160227825Stheraven bool try_lock(); 161227825Stheraven 162227825Stheraven template <class _Rep, class _Period> 163227825Stheraven bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); 164227825Stheraven template <class _Clock, class _Duration> 165227825Stheraven bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 166227825Stheraven 167227825Stheraven void unlock(); 168227825Stheraven 169227825Stheraven _LIBCPP_INLINE_VISIBILITY 170241903Sdim void swap(unique_lock& __u) _NOEXCEPT 171227825Stheraven { 172227825Stheraven _VSTD::swap(__m_, __u.__m_); 173227825Stheraven _VSTD::swap(__owns_, __u.__owns_); 174227825Stheraven } 175227825Stheraven _LIBCPP_INLINE_VISIBILITY 176241903Sdim mutex_type* release() _NOEXCEPT 177227825Stheraven { 178227825Stheraven mutex_type* __m = __m_; 179227825Stheraven __m_ = nullptr; 180227825Stheraven __owns_ = false; 181227825Stheraven return __m; 182227825Stheraven } 183227825Stheraven 184227825Stheraven _LIBCPP_INLINE_VISIBILITY 185241903Sdim bool owns_lock() const _NOEXCEPT {return __owns_;} 186227825Stheraven _LIBCPP_INLINE_VISIBILITY 187232950Stheraven _LIBCPP_EXPLICIT 188241903Sdim operator bool () const _NOEXCEPT {return __owns_;} 189227825Stheraven _LIBCPP_INLINE_VISIBILITY 190241903Sdim mutex_type* mutex() const _NOEXCEPT {return __m_;} 191227825Stheraven}; 192227825Stheraven 193227825Stheraventemplate <class _Mutex> 194227825Stheravenvoid 195227825Stheravenunique_lock<_Mutex>::lock() 196227825Stheraven{ 197227825Stheraven if (__m_ == nullptr) 198227825Stheraven __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); 199227825Stheraven if (__owns_) 200227825Stheraven __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); 201227825Stheraven __m_->lock(); 202227825Stheraven __owns_ = true; 203227825Stheraven} 204227825Stheraven 205227825Stheraventemplate <class _Mutex> 206227825Stheravenbool 207227825Stheravenunique_lock<_Mutex>::try_lock() 208227825Stheraven{ 209227825Stheraven if (__m_ == nullptr) 210227825Stheraven __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); 211227825Stheraven if (__owns_) 212227825Stheraven __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); 213227825Stheraven __owns_ = __m_->try_lock(); 214227825Stheraven return __owns_; 215227825Stheraven} 216227825Stheraven 217227825Stheraventemplate <class _Mutex> 218227825Stheraventemplate <class _Rep, class _Period> 219227825Stheravenbool 220227825Stheravenunique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 221227825Stheraven{ 222227825Stheraven if (__m_ == nullptr) 223227825Stheraven __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); 224227825Stheraven if (__owns_) 225227825Stheraven __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); 226227825Stheraven __owns_ = __m_->try_lock_for(__d); 227227825Stheraven return __owns_; 228227825Stheraven} 229227825Stheraven 230227825Stheraventemplate <class _Mutex> 231227825Stheraventemplate <class _Clock, class _Duration> 232227825Stheravenbool 233227825Stheravenunique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 234227825Stheraven{ 235227825Stheraven if (__m_ == nullptr) 236227825Stheraven __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); 237227825Stheraven if (__owns_) 238227825Stheraven __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); 239227825Stheraven __owns_ = __m_->try_lock_until(__t); 240227825Stheraven return __owns_; 241227825Stheraven} 242227825Stheraven 243227825Stheraventemplate <class _Mutex> 244227825Stheravenvoid 245227825Stheravenunique_lock<_Mutex>::unlock() 246227825Stheraven{ 247227825Stheraven if (!__owns_) 248227825Stheraven __throw_system_error(EPERM, "unique_lock::unlock: not locked"); 249227825Stheraven __m_->unlock(); 250227825Stheraven __owns_ = false; 251227825Stheraven} 252227825Stheraven 253227825Stheraventemplate <class _Mutex> 254227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 255227825Stheravenvoid 256241903Sdimswap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT 257241903Sdim {__x.swap(__y);} 258227825Stheraven 259278724Sdim//enum class cv_status 260278724Sdim_LIBCPP_DECLARE_STRONG_ENUM(cv_status) 261227825Stheraven{ 262278724Sdim no_timeout, 263278724Sdim timeout 264227825Stheraven}; 265278724Sdim_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) 266227825Stheraven 267249998Sdimclass _LIBCPP_TYPE_VIS condition_variable 268227825Stheraven{ 269227825Stheraven pthread_cond_t __cv_; 270227825Stheravenpublic: 271227825Stheraven _LIBCPP_INLINE_VISIBILITY 272241903Sdim#ifndef _LIBCPP_HAS_NO_CONSTEXPR 273241903Sdim constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {} 274241903Sdim#else 275227825Stheraven condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;} 276241903Sdim#endif 277227825Stheraven ~condition_variable(); 278227825Stheraven 279227825Stheravenprivate: 280227825Stheraven condition_variable(const condition_variable&); // = delete; 281227825Stheraven condition_variable& operator=(const condition_variable&); // = delete; 282227825Stheraven 283227825Stheravenpublic: 284241903Sdim void notify_one() _NOEXCEPT; 285241903Sdim void notify_all() _NOEXCEPT; 286227825Stheraven 287278724Sdim void wait(unique_lock<mutex>& __lk) _NOEXCEPT; 288227825Stheraven template <class _Predicate> 289227825Stheraven void wait(unique_lock<mutex>& __lk, _Predicate __pred); 290227825Stheraven 291227825Stheraven template <class _Clock, class _Duration> 292227825Stheraven cv_status 293227825Stheraven wait_until(unique_lock<mutex>& __lk, 294227825Stheraven const chrono::time_point<_Clock, _Duration>& __t); 295227825Stheraven 296227825Stheraven template <class _Clock, class _Duration, class _Predicate> 297227825Stheraven bool 298227825Stheraven wait_until(unique_lock<mutex>& __lk, 299227825Stheraven const chrono::time_point<_Clock, _Duration>& __t, 300227825Stheraven _Predicate __pred); 301227825Stheraven 302227825Stheraven template <class _Rep, class _Period> 303227825Stheraven cv_status 304227825Stheraven wait_for(unique_lock<mutex>& __lk, 305227825Stheraven const chrono::duration<_Rep, _Period>& __d); 306227825Stheraven 307227825Stheraven template <class _Rep, class _Period, class _Predicate> 308227825Stheraven bool 309227825Stheraven wait_for(unique_lock<mutex>& __lk, 310227825Stheraven const chrono::duration<_Rep, _Period>& __d, 311227825Stheraven _Predicate __pred); 312227825Stheraven 313227825Stheraven typedef pthread_cond_t* native_handle_type; 314227825Stheraven _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} 315227825Stheraven 316227825Stheravenprivate: 317227825Stheraven void __do_timed_wait(unique_lock<mutex>& __lk, 318278724Sdim chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT; 319227825Stheraven}; 320278724Sdim#endif // !_LIBCPP_HAS_NO_THREADS 321227825Stheraven 322227825Stheraventemplate <class _To, class _Rep, class _Period> 323227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 324227825Stheraventypename enable_if 325227825Stheraven< 326227825Stheraven chrono::__is_duration<_To>::value, 327227825Stheraven _To 328227825Stheraven>::type 329227825Stheraven__ceil(chrono::duration<_Rep, _Period> __d) 330227825Stheraven{ 331227825Stheraven using namespace chrono; 332227825Stheraven _To __r = duration_cast<_To>(__d); 333227825Stheraven if (__r < __d) 334227825Stheraven ++__r; 335227825Stheraven return __r; 336227825Stheraven} 337227825Stheraven 338278724Sdim#ifndef _LIBCPP_HAS_NO_THREADS 339227825Stheraventemplate <class _Predicate> 340227825Stheravenvoid 341227825Stheravencondition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) 342227825Stheraven{ 343227825Stheraven while (!__pred()) 344227825Stheraven wait(__lk); 345227825Stheraven} 346227825Stheraven 347227825Stheraventemplate <class _Clock, class _Duration> 348227825Stheravencv_status 349227825Stheravencondition_variable::wait_until(unique_lock<mutex>& __lk, 350227825Stheraven const chrono::time_point<_Clock, _Duration>& __t) 351227825Stheraven{ 352227825Stheraven using namespace chrono; 353241903Sdim wait_for(__lk, __t - _Clock::now()); 354227825Stheraven return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; 355227825Stheraven} 356227825Stheraven 357227825Stheraventemplate <class _Clock, class _Duration, class _Predicate> 358227825Stheravenbool 359227825Stheravencondition_variable::wait_until(unique_lock<mutex>& __lk, 360227825Stheraven const chrono::time_point<_Clock, _Duration>& __t, 361227825Stheraven _Predicate __pred) 362227825Stheraven{ 363227825Stheraven while (!__pred()) 364227825Stheraven { 365227825Stheraven if (wait_until(__lk, __t) == cv_status::timeout) 366227825Stheraven return __pred(); 367227825Stheraven } 368227825Stheraven return true; 369227825Stheraven} 370227825Stheraven 371227825Stheraventemplate <class _Rep, class _Period> 372227825Stheravencv_status 373227825Stheravencondition_variable::wait_for(unique_lock<mutex>& __lk, 374227825Stheraven const chrono::duration<_Rep, _Period>& __d) 375227825Stheraven{ 376227825Stheraven using namespace chrono; 377241903Sdim if (__d <= __d.zero()) 378241903Sdim return cv_status::timeout; 379241903Sdim typedef time_point<system_clock, duration<long double, nano> > __sys_tpf; 380241903Sdim typedef time_point<system_clock, nanoseconds> __sys_tpi; 381241903Sdim __sys_tpf _Max = __sys_tpi::max(); 382227825Stheraven system_clock::time_point __s_now = system_clock::now(); 383227825Stheraven steady_clock::time_point __c_now = steady_clock::now(); 384241903Sdim if (_Max - __d > __s_now) 385241903Sdim __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d)); 386241903Sdim else 387241903Sdim __do_timed_wait(__lk, __sys_tpi::max()); 388227825Stheraven return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : 389227825Stheraven cv_status::timeout; 390227825Stheraven} 391227825Stheraven 392227825Stheraventemplate <class _Rep, class _Period, class _Predicate> 393227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 394227825Stheravenbool 395227825Stheravencondition_variable::wait_for(unique_lock<mutex>& __lk, 396227825Stheraven const chrono::duration<_Rep, _Period>& __d, 397227825Stheraven _Predicate __pred) 398227825Stheraven{ 399227825Stheraven return wait_until(__lk, chrono::steady_clock::now() + __d, 400227825Stheraven _VSTD::move(__pred)); 401227825Stheraven} 402227825Stheraven 403278724Sdim#endif // !_LIBCPP_HAS_NO_THREADS 404278724Sdim 405227825Stheraven_LIBCPP_END_NAMESPACE_STD 406227825Stheraven 407227825Stheraven#endif // _LIBCPP___MUTEX_BASE 408