OLD | NEW |
(Empty) | |
| 1 // -*- C++ -*- |
| 2 //===--------------------------- mutex ------------------------------------===// |
| 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 |
| 12 #define _LIBCPP_MUTEX |
| 13 |
| 14 /* |
| 15 mutex synopsis |
| 16 |
| 17 namespace std |
| 18 { |
| 19 |
| 20 class mutex |
| 21 { |
| 22 public: |
| 23 constexpr mutex() noexcept; |
| 24 ~mutex(); |
| 25 |
| 26 mutex(const mutex&) = delete; |
| 27 mutex& operator=(const mutex&) = delete; |
| 28 |
| 29 void lock(); |
| 30 bool try_lock(); |
| 31 void unlock(); |
| 32 |
| 33 typedef pthread_mutex_t* native_handle_type; |
| 34 native_handle_type native_handle(); |
| 35 }; |
| 36 |
| 37 class recursive_mutex |
| 38 { |
| 39 public: |
| 40 recursive_mutex(); |
| 41 ~recursive_mutex(); |
| 42 |
| 43 recursive_mutex(const recursive_mutex&) = delete; |
| 44 recursive_mutex& operator=(const recursive_mutex&) = delete; |
| 45 |
| 46 void lock(); |
| 47 bool try_lock() noexcept; |
| 48 void unlock(); |
| 49 |
| 50 typedef pthread_mutex_t* native_handle_type; |
| 51 native_handle_type native_handle(); |
| 52 }; |
| 53 |
| 54 class timed_mutex |
| 55 { |
| 56 public: |
| 57 timed_mutex(); |
| 58 ~timed_mutex(); |
| 59 |
| 60 timed_mutex(const timed_mutex&) = delete; |
| 61 timed_mutex& operator=(const timed_mutex&) = delete; |
| 62 |
| 63 void lock(); |
| 64 bool try_lock(); |
| 65 template <class Rep, class Period> |
| 66 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
| 67 template <class Clock, class Duration> |
| 68 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
; |
| 69 void unlock(); |
| 70 }; |
| 71 |
| 72 class recursive_timed_mutex |
| 73 { |
| 74 public: |
| 75 recursive_timed_mutex(); |
| 76 ~recursive_timed_mutex(); |
| 77 |
| 78 recursive_timed_mutex(const recursive_timed_mutex&) = delete; |
| 79 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; |
| 80 |
| 81 void lock(); |
| 82 bool try_lock() noexcept; |
| 83 template <class Rep, class Period> |
| 84 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
| 85 template <class Clock, class Duration> |
| 86 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
; |
| 87 void unlock(); |
| 88 }; |
| 89 |
| 90 struct defer_lock_t {}; |
| 91 struct try_to_lock_t {}; |
| 92 struct adopt_lock_t {}; |
| 93 |
| 94 constexpr defer_lock_t defer_lock{}; |
| 95 constexpr try_to_lock_t try_to_lock{}; |
| 96 constexpr adopt_lock_t adopt_lock{}; |
| 97 |
| 98 template <class Mutex> |
| 99 class lock_guard |
| 100 { |
| 101 public: |
| 102 typedef Mutex mutex_type; |
| 103 |
| 104 explicit lock_guard(mutex_type& m); |
| 105 lock_guard(mutex_type& m, adopt_lock_t); |
| 106 ~lock_guard(); |
| 107 |
| 108 lock_guard(lock_guard const&) = delete; |
| 109 lock_guard& operator=(lock_guard const&) = delete; |
| 110 }; |
| 111 |
| 112 template <class Mutex> |
| 113 class unique_lock |
| 114 { |
| 115 public: |
| 116 typedef Mutex mutex_type; |
| 117 unique_lock() noexcept; |
| 118 explicit unique_lock(mutex_type& m); |
| 119 unique_lock(mutex_type& m, defer_lock_t) noexcept; |
| 120 unique_lock(mutex_type& m, try_to_lock_t); |
| 121 unique_lock(mutex_type& m, adopt_lock_t); |
| 122 template <class Clock, class Duration> |
| 123 unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& ab
s_time); |
| 124 template <class Rep, class Period> |
| 125 unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time
); |
| 126 ~unique_lock(); |
| 127 |
| 128 unique_lock(unique_lock const&) = delete; |
| 129 unique_lock& operator=(unique_lock const&) = delete; |
| 130 |
| 131 unique_lock(unique_lock&& u) noexcept; |
| 132 unique_lock& operator=(unique_lock&& u) noexcept; |
| 133 |
| 134 void lock(); |
| 135 bool try_lock(); |
| 136 |
| 137 template <class Rep, class Period> |
| 138 bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
| 139 template <class Clock, class Duration> |
| 140 bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
; |
| 141 |
| 142 void unlock(); |
| 143 |
| 144 void swap(unique_lock& u) noexcept; |
| 145 mutex_type* release() noexcept; |
| 146 |
| 147 bool owns_lock() const noexcept; |
| 148 explicit operator bool () const noexcept; |
| 149 mutex_type* mutex() const noexcept; |
| 150 }; |
| 151 |
| 152 template <class Mutex> |
| 153 void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) noexcept; |
| 154 |
| 155 template <class L1, class L2, class... L3> |
| 156 int try_lock(L1&, L2&, L3&...); |
| 157 template <class L1, class L2, class... L3> |
| 158 void lock(L1&, L2&, L3&...); |
| 159 |
| 160 struct once_flag |
| 161 { |
| 162 constexpr once_flag() noexcept; |
| 163 |
| 164 once_flag(const once_flag&) = delete; |
| 165 once_flag& operator=(const once_flag&) = delete; |
| 166 }; |
| 167 |
| 168 template<class Callable, class ...Args> |
| 169 void call_once(once_flag& flag, Callable&& func, Args&&... args); |
| 170 |
| 171 } // std |
| 172 |
| 173 */ |
| 174 |
| 175 #include <__config> |
| 176 #include <__mutex_base> |
| 177 #include <functional> |
| 178 #ifndef _LIBCPP_HAS_NO_VARIADICS |
| 179 #include <tuple> |
| 180 #endif |
| 181 |
| 182 #include <__undef_min_max> |
| 183 |
| 184 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 185 #pragma GCC system_header |
| 186 #endif |
| 187 |
| 188 _LIBCPP_BEGIN_NAMESPACE_STD |
| 189 |
| 190 class _LIBCPP_TYPE_VIS recursive_mutex |
| 191 { |
| 192 pthread_mutex_t __m_; |
| 193 |
| 194 public: |
| 195 recursive_mutex(); |
| 196 ~recursive_mutex(); |
| 197 |
| 198 private: |
| 199 recursive_mutex(const recursive_mutex&); // = delete; |
| 200 recursive_mutex& operator=(const recursive_mutex&); // = delete; |
| 201 |
| 202 public: |
| 203 void lock(); |
| 204 bool try_lock() _NOEXCEPT; |
| 205 void unlock() _NOEXCEPT; |
| 206 |
| 207 typedef pthread_mutex_t* native_handle_type; |
| 208 _LIBCPP_INLINE_VISIBILITY |
| 209 native_handle_type native_handle() {return &__m_;} |
| 210 }; |
| 211 |
| 212 class _LIBCPP_TYPE_VIS timed_mutex |
| 213 { |
| 214 mutex __m_; |
| 215 condition_variable __cv_; |
| 216 bool __locked_; |
| 217 public: |
| 218 timed_mutex(); |
| 219 ~timed_mutex(); |
| 220 |
| 221 private: |
| 222 timed_mutex(const timed_mutex&); // = delete; |
| 223 timed_mutex& operator=(const timed_mutex&); // = delete; |
| 224 |
| 225 public: |
| 226 void lock(); |
| 227 bool try_lock() _NOEXCEPT; |
| 228 template <class _Rep, class _Period> |
| 229 _LIBCPP_INLINE_VISIBILITY |
| 230 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) |
| 231 {return try_lock_until(chrono::steady_clock::now() + __d);} |
| 232 template <class _Clock, class _Duration> |
| 233 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); |
| 234 void unlock() _NOEXCEPT; |
| 235 }; |
| 236 |
| 237 template <class _Clock, class _Duration> |
| 238 bool |
| 239 timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) |
| 240 { |
| 241 using namespace chrono; |
| 242 unique_lock<mutex> __lk(__m_); |
| 243 bool no_timeout = _Clock::now() < __t; |
| 244 while (no_timeout && __locked_) |
| 245 no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; |
| 246 if (!__locked_) |
| 247 { |
| 248 __locked_ = true; |
| 249 return true; |
| 250 } |
| 251 return false; |
| 252 } |
| 253 |
| 254 class _LIBCPP_TYPE_VIS recursive_timed_mutex |
| 255 { |
| 256 mutex __m_; |
| 257 condition_variable __cv_; |
| 258 size_t __count_; |
| 259 pthread_t __id_; |
| 260 public: |
| 261 recursive_timed_mutex(); |
| 262 ~recursive_timed_mutex(); |
| 263 |
| 264 private: |
| 265 recursive_timed_mutex(const recursive_timed_mutex&); // = delete; |
| 266 recursive_timed_mutex& operator=(const recursive_timed_mutex&); // = delete; |
| 267 |
| 268 public: |
| 269 void lock(); |
| 270 bool try_lock() _NOEXCEPT; |
| 271 template <class _Rep, class _Period> |
| 272 _LIBCPP_INLINE_VISIBILITY |
| 273 bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) |
| 274 {return try_lock_until(chrono::steady_clock::now() + __d);} |
| 275 template <class _Clock, class _Duration> |
| 276 bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); |
| 277 void unlock() _NOEXCEPT; |
| 278 }; |
| 279 |
| 280 template <class _Clock, class _Duration> |
| 281 bool |
| 282 recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration
>& __t) |
| 283 { |
| 284 using namespace chrono; |
| 285 pthread_t __id = pthread_self(); |
| 286 unique_lock<mutex> lk(__m_); |
| 287 if (pthread_equal(__id, __id_)) |
| 288 { |
| 289 if (__count_ == numeric_limits<size_t>::max()) |
| 290 return false; |
| 291 ++__count_; |
| 292 return true; |
| 293 } |
| 294 bool no_timeout = _Clock::now() < __t; |
| 295 while (no_timeout && __count_ != 0) |
| 296 no_timeout = __cv_.wait_until(lk, __t) == cv_status::no_timeout; |
| 297 if (__count_ == 0) |
| 298 { |
| 299 __count_ = 1; |
| 300 __id_ = __id; |
| 301 return true; |
| 302 } |
| 303 return false; |
| 304 } |
| 305 |
| 306 template <class _L0, class _L1> |
| 307 int |
| 308 try_lock(_L0& __l0, _L1& __l1) |
| 309 { |
| 310 unique_lock<_L0> __u0(__l0, try_to_lock); |
| 311 if (__u0.owns_lock()) |
| 312 { |
| 313 if (__l1.try_lock()) |
| 314 { |
| 315 __u0.release(); |
| 316 return -1; |
| 317 } |
| 318 else |
| 319 return 1; |
| 320 } |
| 321 return 0; |
| 322 } |
| 323 |
| 324 #ifndef _LIBCPP_HAS_NO_VARIADICS |
| 325 |
| 326 template <class _L0, class _L1, class _L2, class... _L3> |
| 327 int |
| 328 try_lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3&... __l3) |
| 329 { |
| 330 int __r = 0; |
| 331 unique_lock<_L0> __u0(__l0, try_to_lock); |
| 332 if (__u0.owns_lock()) |
| 333 { |
| 334 __r = try_lock(__l1, __l2, __l3...); |
| 335 if (__r == -1) |
| 336 __u0.release(); |
| 337 else |
| 338 ++__r; |
| 339 } |
| 340 return __r; |
| 341 } |
| 342 |
| 343 #endif // _LIBCPP_HAS_NO_VARIADICS |
| 344 |
| 345 template <class _L0, class _L1> |
| 346 void |
| 347 lock(_L0& __l0, _L1& __l1) |
| 348 { |
| 349 while (true) |
| 350 { |
| 351 { |
| 352 unique_lock<_L0> __u0(__l0); |
| 353 if (__l1.try_lock()) |
| 354 { |
| 355 __u0.release(); |
| 356 break; |
| 357 } |
| 358 } |
| 359 sched_yield(); |
| 360 { |
| 361 unique_lock<_L1> __u1(__l1); |
| 362 if (__l0.try_lock()) |
| 363 { |
| 364 __u1.release(); |
| 365 break; |
| 366 } |
| 367 } |
| 368 sched_yield(); |
| 369 } |
| 370 } |
| 371 |
| 372 #ifndef _LIBCPP_HAS_NO_VARIADICS |
| 373 |
| 374 template <class _L0, class _L1, class _L2, class ..._L3> |
| 375 void |
| 376 __lock_first(int __i, _L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) |
| 377 { |
| 378 while (true) |
| 379 { |
| 380 switch (__i) |
| 381 { |
| 382 case 0: |
| 383 { |
| 384 unique_lock<_L0> __u0(__l0); |
| 385 __i = try_lock(__l1, __l2, __l3...); |
| 386 if (__i == -1) |
| 387 { |
| 388 __u0.release(); |
| 389 return; |
| 390 } |
| 391 } |
| 392 ++__i; |
| 393 sched_yield(); |
| 394 break; |
| 395 case 1: |
| 396 { |
| 397 unique_lock<_L1> __u1(__l1); |
| 398 __i = try_lock(__l2, __l3..., __l0); |
| 399 if (__i == -1) |
| 400 { |
| 401 __u1.release(); |
| 402 return; |
| 403 } |
| 404 } |
| 405 if (__i == sizeof...(_L3) + 1) |
| 406 __i = 0; |
| 407 else |
| 408 __i += 2; |
| 409 sched_yield(); |
| 410 break; |
| 411 default: |
| 412 __lock_first(__i - 2, __l2, __l3..., __l0, __l1); |
| 413 return; |
| 414 } |
| 415 } |
| 416 } |
| 417 |
| 418 template <class _L0, class _L1, class _L2, class ..._L3> |
| 419 inline _LIBCPP_INLINE_VISIBILITY |
| 420 void |
| 421 lock(_L0& __l0, _L1& __l1, _L2& __l2, _L3& ...__l3) |
| 422 { |
| 423 __lock_first(0, __l0, __l1, __l2, __l3...); |
| 424 } |
| 425 |
| 426 #endif // _LIBCPP_HAS_NO_VARIADICS |
| 427 |
| 428 struct _LIBCPP_TYPE_VIS once_flag; |
| 429 |
| 430 #ifndef _LIBCPP_HAS_NO_VARIADICS |
| 431 |
| 432 template<class _Callable, class... _Args> |
| 433 _LIBCPP_INLINE_VISIBILITY |
| 434 void call_once(once_flag&, _Callable&&, _Args&&...); |
| 435 |
| 436 #else // _LIBCPP_HAS_NO_VARIADICS |
| 437 |
| 438 template<class _Callable> |
| 439 _LIBCPP_INLINE_VISIBILITY |
| 440 void call_once(once_flag&, _Callable); |
| 441 |
| 442 #endif // _LIBCPP_HAS_NO_VARIADICS |
| 443 |
| 444 struct _LIBCPP_TYPE_VIS_ONLY once_flag |
| 445 { |
| 446 _LIBCPP_INLINE_VISIBILITY |
| 447 _LIBCPP_CONSTEXPR |
| 448 once_flag() _NOEXCEPT : __state_(0) {} |
| 449 |
| 450 private: |
| 451 once_flag(const once_flag&); // = delete; |
| 452 once_flag& operator=(const once_flag&); // = delete; |
| 453 |
| 454 unsigned long __state_; |
| 455 |
| 456 #ifndef _LIBCPP_HAS_NO_VARIADICS |
| 457 template<class _Callable, class... _Args> |
| 458 friend |
| 459 void call_once(once_flag&, _Callable&&, _Args&&...); |
| 460 #else // _LIBCPP_HAS_NO_VARIADICS |
| 461 template<class _Callable> |
| 462 friend |
| 463 void call_once(once_flag&, _Callable); |
| 464 #endif // _LIBCPP_HAS_NO_VARIADICS |
| 465 }; |
| 466 |
| 467 #ifndef _LIBCPP_HAS_NO_VARIADICS |
| 468 |
| 469 template <class _Fp> |
| 470 class __call_once_param |
| 471 { |
| 472 _Fp __f_; |
| 473 public: |
| 474 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
| 475 _LIBCPP_INLINE_VISIBILITY |
| 476 explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {} |
| 477 #else |
| 478 _LIBCPP_INLINE_VISIBILITY |
| 479 explicit __call_once_param(const _Fp& __f) : __f_(__f) {} |
| 480 #endif |
| 481 |
| 482 _LIBCPP_INLINE_VISIBILITY |
| 483 void operator()() |
| 484 { |
| 485 typedef typename __make_tuple_indices<tuple_size<_Fp>::value, 1>::type _
Index; |
| 486 __execute(_Index()); |
| 487 } |
| 488 |
| 489 private: |
| 490 template <size_t ..._Indices> |
| 491 _LIBCPP_INLINE_VISIBILITY |
| 492 void __execute(__tuple_indices<_Indices...>) |
| 493 { |
| 494 __invoke(_VSTD::move(_VSTD::get<0>(__f_)), _VSTD::move(_VSTD::get<_Indic
es>(__f_))...); |
| 495 } |
| 496 }; |
| 497 |
| 498 #else |
| 499 |
| 500 template <class _Fp> |
| 501 class __call_once_param |
| 502 { |
| 503 _Fp __f_; |
| 504 public: |
| 505 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
| 506 _LIBCPP_INLINE_VISIBILITY |
| 507 explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {} |
| 508 #else |
| 509 _LIBCPP_INLINE_VISIBILITY |
| 510 explicit __call_once_param(const _Fp& __f) : __f_(__f) {} |
| 511 #endif |
| 512 |
| 513 _LIBCPP_INLINE_VISIBILITY |
| 514 void operator()() |
| 515 { |
| 516 __f_(); |
| 517 } |
| 518 }; |
| 519 |
| 520 #endif |
| 521 |
| 522 template <class _Fp> |
| 523 void |
| 524 __call_once_proxy(void* __vp) |
| 525 { |
| 526 __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp); |
| 527 (*__p)(); |
| 528 } |
| 529 |
| 530 _LIBCPP_FUNC_VIS void __call_once(volatile unsigned long&, void*, void(*)(void*)
); |
| 531 |
| 532 #ifndef _LIBCPP_HAS_NO_VARIADICS |
| 533 |
| 534 template<class _Callable, class... _Args> |
| 535 inline _LIBCPP_INLINE_VISIBILITY |
| 536 void |
| 537 call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) |
| 538 { |
| 539 if (__flag.__state_ != ~0ul) |
| 540 { |
| 541 typedef tuple<typename decay<_Callable>::type, typename decay<_Args>::ty
pe...> _Gp; |
| 542 __call_once_param<_Gp> __p(_Gp(__decay_copy(_VSTD::forward<_Callable>(__
func)), |
| 543 __decay_copy(_VSTD::forward<_Args>(__args))...))
; |
| 544 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>); |
| 545 } |
| 546 } |
| 547 |
| 548 #else // _LIBCPP_HAS_NO_VARIADICS |
| 549 |
| 550 template<class _Callable> |
| 551 inline _LIBCPP_INLINE_VISIBILITY |
| 552 void |
| 553 call_once(once_flag& __flag, _Callable __func) |
| 554 { |
| 555 if (__flag.__state_ != ~0ul) |
| 556 { |
| 557 __call_once_param<_Callable> __p(__func); |
| 558 __call_once(__flag.__state_, &__p, &__call_once_proxy<_Callable>); |
| 559 } |
| 560 } |
| 561 |
| 562 #endif // _LIBCPP_HAS_NO_VARIADICS |
| 563 |
| 564 _LIBCPP_END_NAMESPACE_STD |
| 565 |
| 566 #endif // _LIBCPP_MUTEX |
OLD | NEW |