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 40 class _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 48 public: 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 57 private: 58 mutex(const mutex&);// = delete; 59 mutex& operator=(const mutex&);// = delete; 60 61 public: 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 70 static_assert(is_nothrow_default_constructible<mutex>::value, 71 "the default constructor for std::mutex must be nothrow"); 72 73 struct _LIBCPP_TYPE_VIS defer_lock_t {}; 74 struct _LIBCPP_TYPE_VIS try_to_lock_t {}; 75 struct _LIBCPP_TYPE_VIS adopt_lock_t {}; 76 77 #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) 78 79 extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock; 80 extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock; 81 extern _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 91 template <class _Mutex> 92 class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) 93 lock_guard 94 { 95 public: 96 typedef _Mutex mutex_type; 97 98 private: 99 mutex_type& __m_; 100 public: 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 111 private: 112 lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE; 113 lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE; 114 }; 115 116 template <class _Mutex> 117 class _LIBCPP_TEMPLATE_VIS unique_lock 118 { 119 public: 120 typedef _Mutex mutex_type; 121 122 private: 123 mutex_type* __m_; 124 bool __owns_; 125 126 public: 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 156 private: 157 unique_lock(unique_lock const&); // = delete; 158 unique_lock& operator=(unique_lock const&); // = delete; 159 160 public: 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 214 template <class _Mutex> 215 void 216 unique_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 226 template <class _Mutex> 227 bool 228 unique_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 238 template <class _Mutex> 239 template <class _Rep, class _Period> 240 bool 241 unique_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 251 template <class _Mutex> 252 template <class _Clock, class _Duration> 253 bool 254 unique_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 264 template <class _Mutex> 265 void 266 unique_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 274 template <class _Mutex> 275 inline _LIBCPP_INLINE_VISIBILITY 276 void 277 swap(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 288 class _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 296 public: 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 305 private: 306 condition_variable(const condition_variable&); // = delete; 307 condition_variable& operator=(const condition_variable&); // = delete; 308 309 public: 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 347 private: 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 353 template <class _To, class _Rep, class _Period> 354 inline _LIBCPP_INLINE_VISIBILITY 355 typename 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 370 template <class _Predicate> 371 void 372 condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) 373 { 374 while (!__pred()) 375 wait(__lk); 376 } 377 378 template <class _Clock, class _Duration> 379 cv_status 380 condition_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 388 template <class _Clock, class _Duration, class _Predicate> 389 bool 390 condition_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 402 template <class _Rep, class _Period> 403 cv_status 404 condition_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 423 template <class _Rep, class _Period, class _Predicate> 424 inline 425 bool 426 condition_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