__mutex_base revision 242945
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#ifdef _LIBCPP_SHARED_LOCK 24227825Stheraven 25227825Stheravennamespace ting { 26227825Stheraventemplate <class _Mutex> class shared_lock; 27227825Stheraventemplate <class _Mutex> class upgrade_lock; 28227825Stheraven} 29227825Stheraven 30227825Stheraven#endif // _LIBCPP_SHARED_LOCK 31227825Stheraven 32227825Stheraven 33227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD 34227825Stheraven 35227825Stheravenclass _LIBCPP_VISIBLE mutex 36227825Stheraven{ 37227825Stheraven pthread_mutex_t __m_; 38227825Stheraven 39227825Stheravenpublic: 40227825Stheraven _LIBCPP_INLINE_VISIBILITY 41241903Sdim#ifndef _LIBCPP_HAS_NO_CONSTEXPR 42241903Sdim constexpr mutex() _NOEXCEPT : __m_(PTHREAD_MUTEX_INITIALIZER) {} 43241903Sdim#else 44241903Sdim mutex() _NOEXCEPT {__m_ = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;} 45241903Sdim#endif 46227825Stheraven ~mutex(); 47227825Stheraven 48227825Stheravenprivate: 49227825Stheraven mutex(const mutex&);// = delete; 50227825Stheraven mutex& operator=(const mutex&);// = delete; 51227825Stheraven 52227825Stheravenpublic: 53227825Stheraven void lock(); 54241903Sdim bool try_lock() _NOEXCEPT; 55241903Sdim void unlock() _NOEXCEPT; 56227825Stheraven 57227825Stheraven typedef pthread_mutex_t* native_handle_type; 58227825Stheraven _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} 59227825Stheraven}; 60227825Stheraven 61227825Stheravenstruct _LIBCPP_VISIBLE defer_lock_t {}; 62227825Stheravenstruct _LIBCPP_VISIBLE try_to_lock_t {}; 63227825Stheravenstruct _LIBCPP_VISIBLE adopt_lock_t {}; 64227825Stheraven 65241903Sdim#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX) 66227825Stheraven 67241903Sdimextern const defer_lock_t defer_lock; 68241903Sdimextern const try_to_lock_t try_to_lock; 69241903Sdimextern const adopt_lock_t adopt_lock; 70227825Stheraven 71241903Sdim#else 72227825Stheraven 73241903Sdimconstexpr defer_lock_t defer_lock = defer_lock_t(); 74241903Sdimconstexpr try_to_lock_t try_to_lock = try_to_lock_t(); 75241903Sdimconstexpr adopt_lock_t adopt_lock = adopt_lock_t(); 76241903Sdim 77241903Sdim#endif 78241903Sdim 79227825Stheraventemplate <class _Mutex> 80227825Stheravenclass _LIBCPP_VISIBLE lock_guard 81227825Stheraven{ 82227825Stheravenpublic: 83227825Stheraven typedef _Mutex mutex_type; 84227825Stheraven 85227825Stheravenprivate: 86227825Stheraven mutex_type& __m_; 87227825Stheravenpublic: 88227825Stheraven 89227825Stheraven _LIBCPP_INLINE_VISIBILITY 90227825Stheraven explicit lock_guard(mutex_type& __m) 91227825Stheraven : __m_(__m) {__m_.lock();} 92227825Stheraven _LIBCPP_INLINE_VISIBILITY 93227825Stheraven lock_guard(mutex_type& __m, adopt_lock_t) 94227825Stheraven : __m_(__m) {} 95227825Stheraven _LIBCPP_INLINE_VISIBILITY 96227825Stheraven ~lock_guard() {__m_.unlock();} 97227825Stheraven 98227825Stheravenprivate: 99227825Stheraven lock_guard(lock_guard const&);// = delete; 100227825Stheraven lock_guard& operator=(lock_guard const&);// = delete; 101227825Stheraven}; 102227825Stheraven 103227825Stheraventemplate <class _Mutex> 104227825Stheravenclass _LIBCPP_VISIBLE unique_lock 105227825Stheraven{ 106227825Stheravenpublic: 107227825Stheraven typedef _Mutex mutex_type; 108227825Stheraven 109227825Stheravenprivate: 110227825Stheraven mutex_type* __m_; 111227825Stheraven bool __owns_; 112227825Stheraven 113227825Stheravenpublic: 114227825Stheraven _LIBCPP_INLINE_VISIBILITY 115241903Sdim unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} 116227825Stheraven _LIBCPP_INLINE_VISIBILITY 117227825Stheraven explicit unique_lock(mutex_type& __m) 118227825Stheraven : __m_(&__m), __owns_(true) {__m_->lock();} 119227825Stheraven _LIBCPP_INLINE_VISIBILITY 120241903Sdim unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT 121227825Stheraven : __m_(&__m), __owns_(false) {} 122227825Stheraven _LIBCPP_INLINE_VISIBILITY 123227825Stheraven unique_lock(mutex_type& __m, try_to_lock_t) 124227825Stheraven : __m_(&__m), __owns_(__m.try_lock()) {} 125227825Stheraven _LIBCPP_INLINE_VISIBILITY 126227825Stheraven unique_lock(mutex_type& __m, adopt_lock_t) 127227825Stheraven : __m_(&__m), __owns_(true) {} 128227825Stheraven template <class _Clock, class _Duration> 129227825Stheraven _LIBCPP_INLINE_VISIBILITY 130227825Stheraven unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) 131227825Stheraven : __m_(&__m), __owns_(__m.try_lock_until(__t)) {} 132227825Stheraven template <class _Rep, class _Period> 133227825Stheraven _LIBCPP_INLINE_VISIBILITY 134227825Stheraven unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) 135227825Stheraven : __m_(&__m), __owns_(__m.try_lock_for(__d)) {} 136227825Stheraven _LIBCPP_INLINE_VISIBILITY 137227825Stheraven ~unique_lock() 138227825Stheraven { 139227825Stheraven if (__owns_) 140227825Stheraven __m_->unlock(); 141227825Stheraven } 142227825Stheraven 143227825Stheravenprivate: 144227825Stheraven unique_lock(unique_lock const&); // = delete; 145227825Stheraven unique_lock& operator=(unique_lock const&); // = delete; 146227825Stheraven 147227825Stheravenpublic: 148227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 149227825Stheraven _LIBCPP_INLINE_VISIBILITY 150241903Sdim unique_lock(unique_lock&& __u) _NOEXCEPT 151227825Stheraven : __m_(__u.__m_), __owns_(__u.__owns_) 152227825Stheraven {__u.__m_ = nullptr; __u.__owns_ = false;} 153227825Stheraven _LIBCPP_INLINE_VISIBILITY 154241903Sdim unique_lock& operator=(unique_lock&& __u) _NOEXCEPT 155227825Stheraven { 156227825Stheraven if (__owns_) 157227825Stheraven __m_->unlock(); 158227825Stheraven __m_ = __u.__m_; 159227825Stheraven __owns_ = __u.__owns_; 160227825Stheraven __u.__m_ = nullptr; 161227825Stheraven __u.__owns_ = false; 162227825Stheraven return *this; 163227825Stheraven } 164227825Stheraven 165227825Stheraven#ifdef _LIBCPP_SHARED_LOCK 166227825Stheraven 167227825Stheraven unique_lock(ting::shared_lock<mutex_type>&&, try_to_lock_t); 168227825Stheraven template <class _Clock, class _Duration> 169227825Stheraven unique_lock(ting::shared_lock<mutex_type>&&, 170227825Stheraven const chrono::time_point<_Clock, _Duration>&); 171227825Stheraven template <class _Rep, class _Period> 172227825Stheraven unique_lock(ting::shared_lock<mutex_type>&&, 173227825Stheraven const chrono::duration<_Rep, _Period>&); 174227825Stheraven 175227825Stheraven explicit unique_lock(ting::upgrade_lock<mutex_type>&&); 176227825Stheraven unique_lock(ting::upgrade_lock<mutex_type>&&, try_to_lock_t); 177227825Stheraven template <class _Clock, class _Duration> 178227825Stheraven unique_lock(ting::upgrade_lock<mutex_type>&&, 179227825Stheraven const chrono::time_point<_Clock, _Duration>&); 180227825Stheraven template <class _Rep, class _Period> 181227825Stheraven unique_lock(ting::upgrade_lock<mutex_type>&&, 182227825Stheraven const chrono::duration<_Rep, _Period>&); 183227825Stheraven 184227825Stheraven#endif // _LIBCPP_SHARED_LOCK 185227825Stheraven 186227825Stheraven#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 187227825Stheraven 188227825Stheraven void lock(); 189227825Stheraven bool try_lock(); 190227825Stheraven 191227825Stheraven template <class _Rep, class _Period> 192227825Stheraven bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); 193227825Stheraven template <class _Clock, class _Duration> 194227825Stheraven bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); 195227825Stheraven 196227825Stheraven void unlock(); 197227825Stheraven 198227825Stheraven _LIBCPP_INLINE_VISIBILITY 199241903Sdim void swap(unique_lock& __u) _NOEXCEPT 200227825Stheraven { 201227825Stheraven _VSTD::swap(__m_, __u.__m_); 202227825Stheraven _VSTD::swap(__owns_, __u.__owns_); 203227825Stheraven } 204227825Stheraven _LIBCPP_INLINE_VISIBILITY 205241903Sdim mutex_type* release() _NOEXCEPT 206227825Stheraven { 207227825Stheraven mutex_type* __m = __m_; 208227825Stheraven __m_ = nullptr; 209227825Stheraven __owns_ = false; 210227825Stheraven return __m; 211227825Stheraven } 212227825Stheraven 213227825Stheraven _LIBCPP_INLINE_VISIBILITY 214241903Sdim bool owns_lock() const _NOEXCEPT {return __owns_;} 215227825Stheraven _LIBCPP_INLINE_VISIBILITY 216232950Stheraven _LIBCPP_EXPLICIT 217241903Sdim operator bool () const _NOEXCEPT {return __owns_;} 218227825Stheraven _LIBCPP_INLINE_VISIBILITY 219241903Sdim mutex_type* mutex() const _NOEXCEPT {return __m_;} 220227825Stheraven}; 221227825Stheraven 222227825Stheraventemplate <class _Mutex> 223227825Stheravenvoid 224227825Stheravenunique_lock<_Mutex>::lock() 225227825Stheraven{ 226227825Stheraven if (__m_ == nullptr) 227227825Stheraven __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); 228227825Stheraven if (__owns_) 229227825Stheraven __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); 230227825Stheraven __m_->lock(); 231227825Stheraven __owns_ = true; 232227825Stheraven} 233227825Stheraven 234227825Stheraventemplate <class _Mutex> 235227825Stheravenbool 236227825Stheravenunique_lock<_Mutex>::try_lock() 237227825Stheraven{ 238227825Stheraven if (__m_ == nullptr) 239227825Stheraven __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); 240227825Stheraven if (__owns_) 241227825Stheraven __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); 242227825Stheraven __owns_ = __m_->try_lock(); 243227825Stheraven return __owns_; 244227825Stheraven} 245227825Stheraven 246227825Stheraventemplate <class _Mutex> 247227825Stheraventemplate <class _Rep, class _Period> 248227825Stheravenbool 249227825Stheravenunique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) 250227825Stheraven{ 251227825Stheraven if (__m_ == nullptr) 252227825Stheraven __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); 253227825Stheraven if (__owns_) 254227825Stheraven __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); 255227825Stheraven __owns_ = __m_->try_lock_for(__d); 256227825Stheraven return __owns_; 257227825Stheraven} 258227825Stheraven 259227825Stheraventemplate <class _Mutex> 260227825Stheraventemplate <class _Clock, class _Duration> 261227825Stheravenbool 262227825Stheravenunique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) 263227825Stheraven{ 264227825Stheraven if (__m_ == nullptr) 265227825Stheraven __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); 266227825Stheraven if (__owns_) 267227825Stheraven __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); 268227825Stheraven __owns_ = __m_->try_lock_until(__t); 269227825Stheraven return __owns_; 270227825Stheraven} 271227825Stheraven 272227825Stheraventemplate <class _Mutex> 273227825Stheravenvoid 274227825Stheravenunique_lock<_Mutex>::unlock() 275227825Stheraven{ 276227825Stheraven if (!__owns_) 277227825Stheraven __throw_system_error(EPERM, "unique_lock::unlock: not locked"); 278227825Stheraven __m_->unlock(); 279227825Stheraven __owns_ = false; 280227825Stheraven} 281227825Stheraven 282227825Stheraventemplate <class _Mutex> 283227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 284227825Stheravenvoid 285241903Sdimswap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT 286241903Sdim {__x.swap(__y);} 287227825Stheraven 288227825Stheravenstruct _LIBCPP_VISIBLE cv_status 289227825Stheraven{ 290242945Stheraven enum __lx { 291227825Stheraven no_timeout, 292227825Stheraven timeout 293227825Stheraven }; 294227825Stheraven 295242945Stheraven __lx __v_; 296227825Stheraven 297242945Stheraven _LIBCPP_INLINE_VISIBILITY cv_status(__lx __v) : __v_(__v) {} 298227825Stheraven _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;} 299227825Stheraven 300227825Stheraven}; 301227825Stheraven 302227825Stheravenclass _LIBCPP_VISIBLE condition_variable 303227825Stheraven{ 304227825Stheraven pthread_cond_t __cv_; 305227825Stheravenpublic: 306227825Stheraven _LIBCPP_INLINE_VISIBILITY 307241903Sdim#ifndef _LIBCPP_HAS_NO_CONSTEXPR 308241903Sdim constexpr condition_variable() : __cv_(PTHREAD_COND_INITIALIZER) {} 309241903Sdim#else 310227825Stheraven condition_variable() {__cv_ = (pthread_cond_t)PTHREAD_COND_INITIALIZER;} 311241903Sdim#endif 312227825Stheraven ~condition_variable(); 313227825Stheraven 314227825Stheravenprivate: 315227825Stheraven condition_variable(const condition_variable&); // = delete; 316227825Stheraven condition_variable& operator=(const condition_variable&); // = delete; 317227825Stheraven 318227825Stheravenpublic: 319241903Sdim void notify_one() _NOEXCEPT; 320241903Sdim void notify_all() _NOEXCEPT; 321227825Stheraven 322227825Stheraven void wait(unique_lock<mutex>& __lk); 323227825Stheraven template <class _Predicate> 324227825Stheraven void wait(unique_lock<mutex>& __lk, _Predicate __pred); 325227825Stheraven 326227825Stheraven template <class _Clock, class _Duration> 327227825Stheraven cv_status 328227825Stheraven wait_until(unique_lock<mutex>& __lk, 329227825Stheraven const chrono::time_point<_Clock, _Duration>& __t); 330227825Stheraven 331227825Stheraven template <class _Clock, class _Duration, class _Predicate> 332227825Stheraven bool 333227825Stheraven wait_until(unique_lock<mutex>& __lk, 334227825Stheraven const chrono::time_point<_Clock, _Duration>& __t, 335227825Stheraven _Predicate __pred); 336227825Stheraven 337227825Stheraven template <class _Rep, class _Period> 338227825Stheraven cv_status 339227825Stheraven wait_for(unique_lock<mutex>& __lk, 340227825Stheraven const chrono::duration<_Rep, _Period>& __d); 341227825Stheraven 342227825Stheraven template <class _Rep, class _Period, class _Predicate> 343227825Stheraven bool 344227825Stheraven wait_for(unique_lock<mutex>& __lk, 345227825Stheraven const chrono::duration<_Rep, _Period>& __d, 346227825Stheraven _Predicate __pred); 347227825Stheraven 348227825Stheraven typedef pthread_cond_t* native_handle_type; 349227825Stheraven _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} 350227825Stheraven 351227825Stheravenprivate: 352227825Stheraven void __do_timed_wait(unique_lock<mutex>& __lk, 353227825Stheraven chrono::time_point<chrono::system_clock, chrono::nanoseconds>); 354227825Stheraven}; 355227825Stheraven 356227825Stheraventemplate <class _To, class _Rep, class _Period> 357227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 358227825Stheraventypename enable_if 359227825Stheraven< 360227825Stheraven chrono::__is_duration<_To>::value, 361227825Stheraven _To 362227825Stheraven>::type 363227825Stheraven__ceil(chrono::duration<_Rep, _Period> __d) 364227825Stheraven{ 365227825Stheraven using namespace chrono; 366227825Stheraven _To __r = duration_cast<_To>(__d); 367227825Stheraven if (__r < __d) 368227825Stheraven ++__r; 369227825Stheraven return __r; 370227825Stheraven} 371227825Stheraven 372227825Stheraventemplate <class _Predicate> 373227825Stheravenvoid 374227825Stheravencondition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) 375227825Stheraven{ 376227825Stheraven while (!__pred()) 377227825Stheraven wait(__lk); 378227825Stheraven} 379227825Stheraven 380227825Stheraventemplate <class _Clock, class _Duration> 381227825Stheravencv_status 382227825Stheravencondition_variable::wait_until(unique_lock<mutex>& __lk, 383227825Stheraven const chrono::time_point<_Clock, _Duration>& __t) 384227825Stheraven{ 385227825Stheraven using namespace chrono; 386241903Sdim wait_for(__lk, __t - _Clock::now()); 387227825Stheraven return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; 388227825Stheraven} 389227825Stheraven 390227825Stheraventemplate <class _Clock, class _Duration, class _Predicate> 391227825Stheravenbool 392227825Stheravencondition_variable::wait_until(unique_lock<mutex>& __lk, 393227825Stheraven const chrono::time_point<_Clock, _Duration>& __t, 394227825Stheraven _Predicate __pred) 395227825Stheraven{ 396227825Stheraven while (!__pred()) 397227825Stheraven { 398227825Stheraven if (wait_until(__lk, __t) == cv_status::timeout) 399227825Stheraven return __pred(); 400227825Stheraven } 401227825Stheraven return true; 402227825Stheraven} 403227825Stheraven 404227825Stheraventemplate <class _Rep, class _Period> 405227825Stheravencv_status 406227825Stheravencondition_variable::wait_for(unique_lock<mutex>& __lk, 407227825Stheraven const chrono::duration<_Rep, _Period>& __d) 408227825Stheraven{ 409227825Stheraven using namespace chrono; 410241903Sdim if (__d <= __d.zero()) 411241903Sdim return cv_status::timeout; 412241903Sdim typedef time_point<system_clock, duration<long double, nano> > __sys_tpf; 413241903Sdim typedef time_point<system_clock, nanoseconds> __sys_tpi; 414241903Sdim __sys_tpf _Max = __sys_tpi::max(); 415227825Stheraven system_clock::time_point __s_now = system_clock::now(); 416227825Stheraven steady_clock::time_point __c_now = steady_clock::now(); 417241903Sdim if (_Max - __d > __s_now) 418241903Sdim __do_timed_wait(__lk, __s_now + __ceil<nanoseconds>(__d)); 419241903Sdim else 420241903Sdim __do_timed_wait(__lk, __sys_tpi::max()); 421227825Stheraven return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : 422227825Stheraven cv_status::timeout; 423227825Stheraven} 424227825Stheraven 425227825Stheraventemplate <class _Rep, class _Period, class _Predicate> 426227825Stheraveninline _LIBCPP_INLINE_VISIBILITY 427227825Stheravenbool 428227825Stheravencondition_variable::wait_for(unique_lock<mutex>& __lk, 429227825Stheraven const chrono::duration<_Rep, _Period>& __d, 430227825Stheraven _Predicate __pred) 431227825Stheraven{ 432227825Stheraven return wait_until(__lk, chrono::steady_clock::now() + __d, 433227825Stheraven _VSTD::move(__pred)); 434227825Stheraven} 435227825Stheraven 436227825Stheraven_LIBCPP_END_NAMESPACE_STD 437227825Stheraven 438227825Stheraven#endif // _LIBCPP___MUTEX_BASE 439