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