__mutex_base revision 262801
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 25249998Sdimclass _LIBCPP_TYPE_VIS mutex 26227825Stheraven{ 27227825Stheraven pthread_mutex_t __m_; 28227825Stheraven 29227825Stheravenpublic: 30227825Stheraven _LIBCPP_INLINE_VISIBILITY 31241903Sdim#ifndef _LIBCPP_HAS_NO_CONSTEXPR 32241903Sdim constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {} 33241903Sdim#else 34241903Sdim mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;} 35241903Sdim#endif 36227825Stheraven ~mutex(); 37227825Stheraven 38227825Stheravenprivate: 39227825Stheraven mutex(const mutex&);// = delete; 40227825Stheraven mutex& operator=(const mutex&);// = delete; 41227825Stheraven 42227825Stheravenpublic: 43227825Stheraven void lock(); 44241903Sdim bool try_lock() _NOEXCEPT; 45241903Sdim void unlock() _NOEXCEPT; 46227825Stheraven 47227825Stheraven typedef pthread_mutex_t* native_handle_type; 48227825Stheraven _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} 49227825Stheraven}; 50227825Stheraven 51249998Sdimstruct _LIBCPP_TYPE_VIS defer_lock_t {}; 52249998Sdimstruct _LIBCPP_TYPE_VIS try_to_lock_t {}; 53249998Sdimstruct _LIBCPP_TYPE_VIS adopt_lock_t {}; 54227825Stheraven 55241903Sdim#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX) 56227825Stheraven 57241903Sdimextern const defer_lock_t defer_lock; 58241903Sdimextern const try_to_lock_t try_to_lock; 59241903Sdimextern const adopt_lock_t adopt_lock; 60227825Stheraven 61241903Sdim#else 62227825Stheraven 63241903Sdimconstexpr defer_lock_t defer_lock = defer_lock_t(); 64241903Sdimconstexpr try_to_lock_t try_to_lock = try_to_lock_t(); 65241903Sdimconstexpr adopt_lock_t adopt_lock = adopt_lock_t(); 66241903Sdim 67241903Sdim#endif 68241903Sdim 69227825Stheraventemplate <class _Mutex> 70262801Sdimclass _LIBCPP_TYPE_VIS_ONLY lock_guard 71227825Stheraven{ 72227825Stheravenpublic: 73227825Stheraven typedef _Mutex mutex_type; 74227825Stheraven 75227825Stheravenprivate: 76227825Stheraven mutex_type& __m_; 77227825Stheravenpublic: 78227825Stheraven 79227825Stheraven _LIBCPP_INLINE_VISIBILITY 80227825Stheraven explicit lock_guard(mutex_type& __m) 81227825Stheraven : __m_(__m) {__m_.lock();} 82227825Stheraven _LIBCPP_INLINE_VISIBILITY 83227825Stheraven lock_guard(mutex_type& __m, adopt_lock_t) 84227825Stheraven : __m_(__m) {} 85227825Stheraven _LIBCPP_INLINE_VISIBILITY 86227825Stheraven ~lock_guard() {__m_.unlock();} 87227825Stheraven 88227825Stheravenprivate: 89227825Stheraven lock_guard(lock_guard const&);// = delete; 90227825Stheraven lock_guard& operator=(lock_guard const&);// = delete; 91227825Stheraven}; 92227825Stheraven 93227825Stheraventemplate <class _Mutex> 94262801Sdimclass _LIBCPP_TYPE_VIS_ONLY unique_lock 95227825Stheraven{ 96227825Stheravenpublic: 97227825Stheraven typedef _Mutex mutex_type; 98227825Stheraven 99227825Stheravenprivate: 100227825Stheraven mutex_type* __m_; 101227825Stheraven bool __owns_; 102227825Stheraven 103227825Stheravenpublic: 104227825Stheraven _LIBCPP_INLINE_VISIBILITY 105241903Sdim unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 106227825Stheraven _LIBCPP_INLINE_VISIBILITY 107227825Stheraven explicit unique_lock(mutex_type& __m) 108227825Stheraven : __m_(&__m), __owns_(true) {__m_->lock();} 109227825Stheraven _LIBCPP_INLINE_VISIBILITY 110241903Sdim unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 111227825Stheraven : __m_(&__m), __owns_(false) {} 112227825Stheraven _LIBCPP_INLINE_VISIBILITY 113227825Stheraven unique_lock(mutex_type& __m, try_to_lock_t) 114227825Stheraven : __m_(&__m), __owns_(__m.try_lock()) {} 115227825Stheraven _LIBCPP_INLINE_VISIBILITY 116227825Stheraven unique_lock(mutex_type& __m, adopt_lock_t) 117227825Stheraven : __m_(&__m), __owns_(true) {} 118227825Stheraven template <class _Clock, class _Duration> 119227825Stheraven _LIBCPP_INLINE_VISIBILITY 120227825Stheraven unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) 121227825Stheraven : __m_(&__m), __owns_(__m.try_lock_until(__t)) {} 122227825Stheraven template <class _Rep, class _Period> 123227825Stheraven _LIBCPP_INLINE_VISIBILITY 124227825Stheraven unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) 125227825Stheraven : __m_(&__m), __owns_(__m.try_lock_for(__d)) {} 126227825Stheraven _LIBCPP_INLINE_VISIBILITY 127227825Stheraven ~unique_lock() 128227825Stheraven { 129227825Stheraven if (__owns_) 130227825Stheraven __m_->unlock(); 131227825Stheraven } 132227825Stheraven 133227825Stheravenprivate: 134227825Stheraven unique_lock(unique_lock const&); // = delete; 135227825Stheraven unique_lock& operator=(unique_lock const&); // = delete; 136227825Stheraven 137227825Stheravenpublic: 138227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 139227825Stheraven _LIBCPP_INLINE_VISIBILITY 140241903Sdim unique_lock(unique_lock&& __u) _NOEXCEPT 141227825Stheraven : __m_(__u.__m_), __owns_(__u.__owns_) 142227825Stheraven {__u.__m_ = nullptr; __u.__owns_ = false;} 143227825Stheraven _LIBCPP_INLINE_VISIBILITY 144241903Sdim unique_lock& operator=(unique_lock&& __u) _NOEXCEPT 145227825Stheraven { 146227825Stheraven if (__owns_) 147227825Stheraven __m_->unlock(); 148227825Stheraven __m_ = __u.__m_; 149227825Stheraven __owns_ = __u.__owns_; 150227825Stheraven __u.__m_ = nullptr; 151227825Stheraven __u.__owns_ = false; 152227825Stheraven return *this; 153227825Stheraven } 154227825Stheraven 155227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 156227825Stheraven 157227825Stheraven void lock(); 158227825Stheraven bool try_lock(); 159227825Stheraven 160227825Stheraven template <class _Rep, class _Period> 161227825Stheraven bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); 162227825Stheraven template <class _Clock, class _Duration> 163227825Stheraven bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 164227825Stheraven 165227825Stheraven void unlock(); 166227825Stheraven 167227825Stheraven _LIBCPP_INLINE_VISIBILITY 168241903Sdim void swap(unique_lock& __u) _NOEXCEPT 169227825Stheraven { 170227825Stheraven _VSTD::swap(__m_, __u.__m_); 171227825Stheraven _VSTD::swap(__owns_, __u.__owns_); 172227825Stheraven } 173227825Stheraven _LIBCPP_INLINE_VISIBILITY 174241903Sdim mutex_type* release() _NOEXCEPT 175227825Stheraven { 176227825Stheraven mutex_type* __m = __m_; 177227825Stheraven __m_ = nullptr; 178227825Stheraven __owns_ = false; 179227825Stheraven return __m; 180227825Stheraven } 181227825Stheraven 182227825Stheraven _LIBCPP_INLINE_VISIBILITY 183241903Sdim bool owns_lock() const _NOEXCEPT {return __owns_;} 184227825Stheraven _LIBCPP_INLINE_VISIBILITY 185232950Stheraven _LIBCPP_EXPLICIT 186241903Sdim operator bool () const _NOEXCEPT {return __owns_;} 187227825Stheraven _LIBCPP_INLINE_VISIBILITY 188241903Sdim mutex_type* mutex() const _NOEXCEPT {return __m_;} 189227825Stheraven}; 190227825Stheraven 191227825Stheraventemplate <class _Mutex> 192227825Stheravenvoid 193227825Stheravenunique_lock<_Mutex>::lock() 194227825Stheraven{ 195227825Stheraven if (__m_ == nullptr) 196227825Stheraven __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); 197227825Stheraven if (__owns_) 198227825Stheraven __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); 199227825Stheraven __m_->lock(); 200227825Stheraven __owns_ = true; 201227825Stheraven} 202227825Stheraven 203227825Stheraventemplate <class _Mutex> 204227825Stheravenbool 205227825Stheravenunique_lock<_Mutex>::try_lock() 206227825Stheraven{ 207227825Stheraven if (__m_ == nullptr) 208227825Stheraven __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); 209227825Stheraven if (__owns_) 210227825Stheraven __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); 211227825Stheraven __owns_ = __m_->try_lock(); 212227825Stheraven return __owns_; 213227825Stheraven} 214227825Stheraven 215227825Stheraventemplate <class _Mutex> 216227825Stheraventemplate <class _Rep, class _Period> 217227825Stheravenbool 218227825Stheravenunique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 219227825Stheraven{ 220227825Stheraven if (__m_ == nullptr) 221227825Stheraven __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); 222227825Stheraven if (__owns_) 223227825Stheraven __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); 224227825Stheraven __owns_ = __m_->try_lock_for(__d); 225227825Stheraven return __owns_; 226227825Stheraven} 227227825Stheraven 228227825Stheraventemplate <class _Mutex> 229227825Stheraventemplate <class _Clock, class _Duration> 230227825Stheravenbool 231227825Stheravenunique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 232227825Stheraven{ 233227825Stheraven if (__m_ == nullptr) 234227825Stheraven __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); 235227825Stheraven if (__owns_) 236227825Stheraven __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); 237227825Stheraven __owns_ = __m_->try_lock_until(__t); 238227825Stheraven return __owns_; 239227825Stheraven} 240227825Stheraven 241227825Stheraventemplate <class _Mutex> 242227825Stheravenvoid 243227825Stheravenunique_lock<_Mutex>::unlock() 244227825Stheraven{ 245227825Stheraven if (!__owns_) 246227825Stheraven __throw_system_error(EPERM, "unique_lock::unlock: not locked"); 247227825Stheraven __m_->unlock(); 248227825Stheraven __owns_ = false; 249227825Stheraven} 250227825Stheraven 251227825Stheraventemplate <class _Mutex> 252227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 253227825Stheravenvoid 254241903Sdimswap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT 255241903Sdim {__x.swap(__y);} 256227825Stheraven 257249998Sdimstruct _LIBCPP_TYPE_VIS cv_status 258227825Stheraven{ 259242945Stheraven enum __lx { 260227825Stheraven no_timeout, 261227825Stheraven timeout 262227825Stheraven }; 263227825Stheraven 264242945Stheraven __lx __v_; 265227825Stheraven 266242945Stheraven _LIBCPP_INLINE_VISIBILITY cv_status(__lx __v) : __v_(__v) {} 267227825Stheraven _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;} 268227825Stheraven 269227825Stheraven}; 270227825Stheraven 271249998Sdimclass _LIBCPP_TYPE_VIS condition_variable 272227825Stheraven{ 273227825Stheraven pthread_cond_t __cv_; 274227825Stheravenpublic: 275227825Stheraven _LIBCPP_INLINE_VISIBILITY 276241903Sdim#ifndef _LIBCPP_HAS_NO_CONSTEXPR 277241903Sdim constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {} 278241903Sdim#else 279227825Stheraven condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;} 280241903Sdim#endif 281227825Stheraven ~condition_variable(); 282227825Stheraven 283227825Stheravenprivate: 284227825Stheraven condition_variable(const condition_variable&); // = delete; 285227825Stheraven condition_variable& operator=(const condition_variable&); // = delete; 286227825Stheraven 287227825Stheravenpublic: 288241903Sdim void notify_one() _NOEXCEPT; 289241903Sdim void notify_all() _NOEXCEPT; 290227825Stheraven 291227825Stheraven void wait(unique_lock<mutex>& __lk); 292227825Stheraven template <class _Predicate> 293227825Stheraven void wait(unique_lock<mutex>& __lk, _Predicate __pred); 294227825Stheraven 295227825Stheraven template <class _Clock, class _Duration> 296227825Stheraven cv_status 297227825Stheraven wait_until(unique_lock<mutex>& __lk, 298227825Stheraven const chrono::time_point<_Clock, _Duration>& __t); 299227825Stheraven 300227825Stheraven template <class _Clock, class _Duration, class _Predicate> 301227825Stheraven bool 302227825Stheraven wait_until(unique_lock<mutex>& __lk, 303227825Stheraven const chrono::time_point<_Clock, _Duration>& __t, 304227825Stheraven _Predicate __pred); 305227825Stheraven 306227825Stheraven template <class _Rep, class _Period> 307227825Stheraven cv_status 308227825Stheraven wait_for(unique_lock<mutex>& __lk, 309227825Stheraven const chrono::duration<_Rep, _Period>& __d); 310227825Stheraven 311227825Stheraven template <class _Rep, class _Period, class _Predicate> 312227825Stheraven bool 313227825Stheraven wait_for(unique_lock<mutex>& __lk, 314227825Stheraven const chrono::duration<_Rep, _Period>& __d, 315227825Stheraven _Predicate __pred); 316227825Stheraven 317227825Stheraven typedef pthread_cond_t* native_handle_type; 318227825Stheraven _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} 319227825Stheraven 320227825Stheravenprivate: 321227825Stheraven void __do_timed_wait(unique_lock<mutex>& __lk, 322227825Stheraven chrono::time_point<chrono::system_clock, chrono::nanoseconds>); 323227825Stheraven}; 324227825Stheraven 325227825Stheraventemplate <class _To, class _Rep, class _Period> 326227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 327227825Stheraventypename enable_if 328227825Stheraven< 329227825Stheraven chrono::__is_duration<_To>::value, 330227825Stheraven _To 331227825Stheraven>::type 332227825Stheraven__ceil(chrono::duration<_Rep, _Period> __d) 333227825Stheraven{ 334227825Stheraven using namespace chrono; 335227825Stheraven _To __r = duration_cast<_To>(__d); 336227825Stheraven if (__r < __d) 337227825Stheraven ++__r; 338227825Stheraven return __r; 339227825Stheraven} 340227825Stheraven 341227825Stheraventemplate <class _Predicate> 342227825Stheravenvoid 343227825Stheravencondition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) 344227825Stheraven{ 345227825Stheraven while (!__pred()) 346227825Stheraven wait(__lk); 347227825Stheraven} 348227825Stheraven 349227825Stheraventemplate <class _Clock, class _Duration> 350227825Stheravencv_status 351227825Stheravencondition_variable::wait_until(unique_lock<mutex>& __lk, 352227825Stheraven const chrono::time_point<_Clock, _Duration>& __t) 353227825Stheraven{ 354227825Stheraven using namespace chrono; 355241903Sdim wait_for(__lk, __t - _Clock::now()); 356227825Stheraven return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; 357227825Stheraven} 358227825Stheraven 359227825Stheraventemplate <class _Clock, class _Duration, class _Predicate> 360227825Stheravenbool 361227825Stheravencondition_variable::wait_until(unique_lock<mutex>& __lk, 362227825Stheraven const chrono::time_point<_Clock, _Duration>& __t, 363227825Stheraven _Predicate __pred) 364227825Stheraven{ 365227825Stheraven while (!__pred()) 366227825Stheraven { 367227825Stheraven if (wait_until(__lk, __t) == cv_status::timeout) 368227825Stheraven return __pred(); 369227825Stheraven } 370227825Stheraven return true; 371227825Stheraven} 372227825Stheraven 373227825Stheraventemplate <class _Rep, class _Period> 374227825Stheravencv_status 375227825Stheravencondition_variable::wait_for(unique_lock<mutex>& __lk, 376227825Stheraven const chrono::duration<_Rep, _Period>& __d) 377227825Stheraven{ 378227825Stheraven using namespace chrono; 379241903Sdim if (__d <= __d.zero()) 380241903Sdim return cv_status::timeout; 381241903Sdim typedef time_point<system_clock, duration<long double, nano> > __sys_tpf; 382241903Sdim typedef time_point<system_clock, nanoseconds> __sys_tpi; 383241903Sdim __sys_tpf _Max = __sys_tpi::max(); 384227825Stheraven system_clock::time_point __s_now = system_clock::now(); 385227825Stheraven steady_clock::time_point __c_now = steady_clock::now(); 386241903Sdim if (_Max - __d > __s_now) 387241903Sdim __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d)); 388241903Sdim else 389241903Sdim __do_timed_wait(__lk, __sys_tpi::max()); 390227825Stheraven return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : 391227825Stheraven cv_status::timeout; 392227825Stheraven} 393227825Stheraven 394227825Stheraventemplate <class _Rep, class _Period, class _Predicate> 395227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 396227825Stheravenbool 397227825Stheravencondition_variable::wait_for(unique_lock<mutex>& __lk, 398227825Stheraven const chrono::duration<_Rep, _Period>& __d, 399227825Stheraven _Predicate __pred) 400227825Stheraven{ 401227825Stheraven return wait_until(__lk, chrono::steady_clock::now() + __d, 402227825Stheraven _VSTD::move(__pred)); 403227825Stheraven} 404227825Stheraven 405227825Stheraven_LIBCPP_END_NAMESPACE_STD 406227825Stheraven 407227825Stheraven#endif // _LIBCPP___MUTEX_BASE 408