1// <mutex> -*- C++ -*- 2 3// Copyright (C) 2003-2017 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 3, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// Under Section 7 of GPL version 3, you are granted additional 17// permissions described in the GCC Runtime Library Exception, version 18// 3.1, as published by the Free Software Foundation. 19 20// You should have received a copy of the GNU General Public License and 21// a copy of the GCC Runtime Library Exception along with this program; 22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23// <http://www.gnu.org/licenses/>. 24 25/** @file include/mutex 26 * This is a Standard C++ Library header. 27 */ 28 29#ifndef _GLIBCXX_MUTEX 30#define _GLIBCXX_MUTEX 1 31 32#pragma GCC system_header 33 34#if __cplusplus < 201103L 35# include <bits/c++0x_warning.h> 36#else 37 38#include <tuple> 39#include <chrono> 40#include <exception> 41#include <type_traits> 42#include <system_error> 43#include <bits/std_mutex.h> 44#if ! _GTHREAD_USE_MUTEX_TIMEDLOCK 45# include <condition_variable> 46# include <thread> 47#endif 48#ifndef _GLIBCXX_HAVE_TLS 49# include <bits/std_function.h> 50#endif 51 52#ifdef _GLIBCXX_USE_C99_STDINT_TR1 53 54namespace std _GLIBCXX_VISIBILITY(default) 55{ 56_GLIBCXX_BEGIN_NAMESPACE_VERSION 57 58 /** 59 * @ingroup mutexes 60 * @{ 61 */ 62 63#ifdef _GLIBCXX_HAS_GTHREADS 64 65 // Common base class for std::recursive_mutex and std::recursive_timed_mutex 66 class __recursive_mutex_base 67 { 68 protected: 69 typedef __gthread_recursive_mutex_t __native_type; 70 71 __recursive_mutex_base(const __recursive_mutex_base&) = delete; 72 __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; 73 74#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT 75 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT; 76 77 __recursive_mutex_base() = default; 78#else 79 __native_type _M_mutex; 80 81 __recursive_mutex_base() 82 { 83 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) 84 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); 85 } 86 87 ~__recursive_mutex_base() 88 { __gthread_recursive_mutex_destroy(&_M_mutex); } 89#endif 90 }; 91 92 /// The standard recursive mutex type. 93 class recursive_mutex : private __recursive_mutex_base 94 { 95 public: 96 typedef __native_type* native_handle_type; 97 98 recursive_mutex() = default; 99 ~recursive_mutex() = default; 100 101 recursive_mutex(const recursive_mutex&) = delete; 102 recursive_mutex& operator=(const recursive_mutex&) = delete; 103 104 void 105 lock() 106 { 107 int __e = __gthread_recursive_mutex_lock(&_M_mutex); 108 109 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 110 if (__e) 111 __throw_system_error(__e); 112 } 113 114 bool 115 try_lock() noexcept 116 { 117 // XXX EINVAL, EAGAIN, EBUSY 118 return !__gthread_recursive_mutex_trylock(&_M_mutex); 119 } 120 121 void 122 unlock() 123 { 124 // XXX EINVAL, EAGAIN, EBUSY 125 __gthread_recursive_mutex_unlock(&_M_mutex); 126 } 127 128 native_handle_type 129 native_handle() noexcept 130 { return &_M_mutex; } 131 }; 132 133#if _GTHREAD_USE_MUTEX_TIMEDLOCK 134 template<typename _Derived> 135 class __timed_mutex_impl 136 { 137 protected: 138 typedef chrono::high_resolution_clock __clock_t; 139 140 template<typename _Rep, typename _Period> 141 bool 142 _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 143 { 144 using chrono::steady_clock; 145 auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime); 146 if (ratio_greater<steady_clock::period, _Period>()) 147 ++__rt; 148 return _M_try_lock_until(steady_clock::now() + __rt); 149 } 150 151 template<typename _Duration> 152 bool 153 _M_try_lock_until(const chrono::time_point<__clock_t, 154 _Duration>& __atime) 155 { 156 auto __s = chrono::time_point_cast<chrono::seconds>(__atime); 157 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 158 159 __gthread_time_t __ts = { 160 static_cast<std::time_t>(__s.time_since_epoch().count()), 161 static_cast<long>(__ns.count()) 162 }; 163 164 return static_cast<_Derived*>(this)->_M_timedlock(__ts); 165 } 166 167 template<typename _Clock, typename _Duration> 168 bool 169 _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 170 { 171 auto __rtime = __atime - _Clock::now(); 172 return _M_try_lock_until(__clock_t::now() + __rtime); 173 } 174 }; 175 176 /// The standard timed mutex type. 177 class timed_mutex 178 : private __mutex_base, public __timed_mutex_impl<timed_mutex> 179 { 180 public: 181 typedef __native_type* native_handle_type; 182 183 timed_mutex() = default; 184 ~timed_mutex() = default; 185 186 timed_mutex(const timed_mutex&) = delete; 187 timed_mutex& operator=(const timed_mutex&) = delete; 188 189 void 190 lock() 191 { 192 int __e = __gthread_mutex_lock(&_M_mutex); 193 194 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 195 if (__e) 196 __throw_system_error(__e); 197 } 198 199 bool 200 try_lock() noexcept 201 { 202 // XXX EINVAL, EAGAIN, EBUSY 203 return !__gthread_mutex_trylock(&_M_mutex); 204 } 205 206 template <class _Rep, class _Period> 207 bool 208 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 209 { return _M_try_lock_for(__rtime); } 210 211 template <class _Clock, class _Duration> 212 bool 213 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 214 { return _M_try_lock_until(__atime); } 215 216 void 217 unlock() 218 { 219 // XXX EINVAL, EAGAIN, EBUSY 220 __gthread_mutex_unlock(&_M_mutex); 221 } 222 223 native_handle_type 224 native_handle() noexcept 225 { return &_M_mutex; } 226 227 private: 228 friend class __timed_mutex_impl<timed_mutex>; 229 230 bool 231 _M_timedlock(const __gthread_time_t& __ts) 232 { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); } 233 }; 234 235 /// recursive_timed_mutex 236 class recursive_timed_mutex 237 : private __recursive_mutex_base, 238 public __timed_mutex_impl<recursive_timed_mutex> 239 { 240 public: 241 typedef __native_type* native_handle_type; 242 243 recursive_timed_mutex() = default; 244 ~recursive_timed_mutex() = default; 245 246 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 247 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 248 249 void 250 lock() 251 { 252 int __e = __gthread_recursive_mutex_lock(&_M_mutex); 253 254 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 255 if (__e) 256 __throw_system_error(__e); 257 } 258 259 bool 260 try_lock() noexcept 261 { 262 // XXX EINVAL, EAGAIN, EBUSY 263 return !__gthread_recursive_mutex_trylock(&_M_mutex); 264 } 265 266 template <class _Rep, class _Period> 267 bool 268 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 269 { return _M_try_lock_for(__rtime); } 270 271 template <class _Clock, class _Duration> 272 bool 273 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 274 { return _M_try_lock_until(__atime); } 275 276 void 277 unlock() 278 { 279 // XXX EINVAL, EAGAIN, EBUSY 280 __gthread_recursive_mutex_unlock(&_M_mutex); 281 } 282 283 native_handle_type 284 native_handle() noexcept 285 { return &_M_mutex; } 286 287 private: 288 friend class __timed_mutex_impl<recursive_timed_mutex>; 289 290 bool 291 _M_timedlock(const __gthread_time_t& __ts) 292 { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); } 293 }; 294 295#else // !_GTHREAD_USE_MUTEX_TIMEDLOCK 296 297 /// timed_mutex 298 class timed_mutex 299 { 300 mutex _M_mut; 301 condition_variable _M_cv; 302 bool _M_locked = false; 303 304 public: 305 306 timed_mutex() = default; 307 ~timed_mutex() { __glibcxx_assert( !_M_locked ); } 308 309 timed_mutex(const timed_mutex&) = delete; 310 timed_mutex& operator=(const timed_mutex&) = delete; 311 312 void 313 lock() 314 { 315 unique_lock<mutex> __lk(_M_mut); 316 _M_cv.wait(__lk, [&]{ return !_M_locked; }); 317 _M_locked = true; 318 } 319 320 bool 321 try_lock() 322 { 323 lock_guard<mutex> __lk(_M_mut); 324 if (_M_locked) 325 return false; 326 _M_locked = true; 327 return true; 328 } 329 330 template<typename _Rep, typename _Period> 331 bool 332 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 333 { 334 unique_lock<mutex> __lk(_M_mut); 335 if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; })) 336 return false; 337 _M_locked = true; 338 return true; 339 } 340 341 template<typename _Clock, typename _Duration> 342 bool 343 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 344 { 345 unique_lock<mutex> __lk(_M_mut); 346 if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; })) 347 return false; 348 _M_locked = true; 349 return true; 350 } 351 352 void 353 unlock() 354 { 355 lock_guard<mutex> __lk(_M_mut); 356 __glibcxx_assert( _M_locked ); 357 _M_locked = false; 358 _M_cv.notify_one(); 359 } 360 }; 361 362 /// recursive_timed_mutex 363 class recursive_timed_mutex 364 { 365 mutex _M_mut; 366 condition_variable _M_cv; 367 thread::id _M_owner; 368 unsigned _M_count = 0; 369 370 // Predicate type that tests whether the current thread can lock a mutex. 371 struct _Can_lock 372 { 373 // Returns true if the mutex is unlocked or is locked by _M_caller. 374 bool 375 operator()() const noexcept 376 { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; } 377 378 const recursive_timed_mutex* _M_mx; 379 thread::id _M_caller; 380 }; 381 382 public: 383 384 recursive_timed_mutex() = default; 385 ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); } 386 387 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 388 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 389 390 void 391 lock() 392 { 393 auto __id = this_thread::get_id(); 394 _Can_lock __can_lock{this, __id}; 395 unique_lock<mutex> __lk(_M_mut); 396 _M_cv.wait(__lk, __can_lock); 397 if (_M_count == -1u) 398 __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3 399 _M_owner = __id; 400 ++_M_count; 401 } 402 403 bool 404 try_lock() 405 { 406 auto __id = this_thread::get_id(); 407 _Can_lock __can_lock{this, __id}; 408 lock_guard<mutex> __lk(_M_mut); 409 if (!__can_lock()) 410 return false; 411 if (_M_count == -1u) 412 return false; 413 _M_owner = __id; 414 ++_M_count; 415 return true; 416 } 417 418 template<typename _Rep, typename _Period> 419 bool 420 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 421 { 422 auto __id = this_thread::get_id(); 423 _Can_lock __can_lock{this, __id}; 424 unique_lock<mutex> __lk(_M_mut); 425 if (!_M_cv.wait_for(__lk, __rtime, __can_lock)) 426 return false; 427 if (_M_count == -1u) 428 return false; 429 _M_owner = __id; 430 ++_M_count; 431 return true; 432 } 433 434 template<typename _Clock, typename _Duration> 435 bool 436 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 437 { 438 auto __id = this_thread::get_id(); 439 _Can_lock __can_lock{this, __id}; 440 unique_lock<mutex> __lk(_M_mut); 441 if (!_M_cv.wait_until(__lk, __atime, __can_lock)) 442 return false; 443 if (_M_count == -1u) 444 return false; 445 _M_owner = __id; 446 ++_M_count; 447 return true; 448 } 449 450 void 451 unlock() 452 { 453 lock_guard<mutex> __lk(_M_mut); 454 __glibcxx_assert( _M_owner == this_thread::get_id() ); 455 __glibcxx_assert( _M_count > 0 ); 456 if (--_M_count == 0) 457 { 458 _M_owner = {}; 459 _M_cv.notify_one(); 460 } 461 } 462 }; 463 464#endif 465#endif // _GLIBCXX_HAS_GTHREADS 466 467 template<typename _Lock> 468 inline unique_lock<_Lock> 469 __try_to_lock(_Lock& __l) 470 { return unique_lock<_Lock>{__l, try_to_lock}; } 471 472 template<int _Idx, bool _Continue = true> 473 struct __try_lock_impl 474 { 475 template<typename... _Lock> 476 static void 477 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 478 { 479 __idx = _Idx; 480 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); 481 if (__lock.owns_lock()) 482 { 483 constexpr bool __cont = _Idx + 2 < sizeof...(_Lock); 484 using __try_locker = __try_lock_impl<_Idx + 1, __cont>; 485 __try_locker::__do_try_lock(__locks, __idx); 486 if (__idx == -1) 487 __lock.release(); 488 } 489 } 490 }; 491 492 template<int _Idx> 493 struct __try_lock_impl<_Idx, false> 494 { 495 template<typename... _Lock> 496 static void 497 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 498 { 499 __idx = _Idx; 500 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); 501 if (__lock.owns_lock()) 502 { 503 __idx = -1; 504 __lock.release(); 505 } 506 } 507 }; 508 509 /** @brief Generic try_lock. 510 * @param __l1 Meets Mutex requirements (try_lock() may throw). 511 * @param __l2 Meets Mutex requirements (try_lock() may throw). 512 * @param __l3 Meets Mutex requirements (try_lock() may throw). 513 * @return Returns -1 if all try_lock() calls return true. Otherwise returns 514 * a 0-based index corresponding to the argument that returned false. 515 * @post Either all arguments are locked, or none will be. 516 * 517 * Sequentially calls try_lock() on each argument. 518 */ 519 template<typename _Lock1, typename _Lock2, typename... _Lock3> 520 int 521 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3) 522 { 523 int __idx; 524 auto __locks = std::tie(__l1, __l2, __l3...); 525 __try_lock_impl<0>::__do_try_lock(__locks, __idx); 526 return __idx; 527 } 528 529 /** @brief Generic lock. 530 * @param __l1 Meets Mutex requirements (try_lock() may throw). 531 * @param __l2 Meets Mutex requirements (try_lock() may throw). 532 * @param __l3 Meets Mutex requirements (try_lock() may throw). 533 * @throw An exception thrown by an argument's lock() or try_lock() member. 534 * @post All arguments are locked. 535 * 536 * All arguments are locked via a sequence of calls to lock(), try_lock() 537 * and unlock(). If the call exits via an exception any locks that were 538 * obtained will be released. 539 */ 540 template<typename _L1, typename _L2, typename... _L3> 541 void 542 lock(_L1& __l1, _L2& __l2, _L3&... __l3) 543 { 544 while (true) 545 { 546 using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>; 547 unique_lock<_L1> __first(__l1); 548 int __idx; 549 auto __locks = std::tie(__l2, __l3...); 550 __try_locker::__do_try_lock(__locks, __idx); 551 if (__idx == -1) 552 { 553 __first.release(); 554 return; 555 } 556 } 557 } 558 559#if __cplusplus >= 201703L 560#define __cpp_lib_scoped_lock 201703 561 /** @brief A scoped lock type for multiple lockable objects. 562 * 563 * A scoped_lock controls mutex ownership within a scope, releasing 564 * ownership in the destructor. 565 */ 566 template<typename... _MutexTypes> 567 class scoped_lock 568 { 569 public: 570 explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...)) 571 { std::lock(__m...); } 572 573 explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept 574 : _M_devices(std::tie(__m...)) 575 { } // calling thread owns mutex 576 577 ~scoped_lock() 578 { 579 std::apply([](_MutexTypes&... __m) { 580 char __i[] __attribute__((__unused__)) = { (__m.unlock(), 0)... }; 581 }, _M_devices); 582 } 583 584 scoped_lock(const scoped_lock&) = delete; 585 scoped_lock& operator=(const scoped_lock&) = delete; 586 587 private: 588 tuple<_MutexTypes&...> _M_devices; 589 }; 590 591 template<> 592 class scoped_lock<> 593 { 594 public: 595 explicit scoped_lock() = default; 596 explicit scoped_lock(adopt_lock_t) noexcept { } 597 ~scoped_lock() = default; 598 599 scoped_lock(const scoped_lock&) = delete; 600 scoped_lock& operator=(const scoped_lock&) = delete; 601 }; 602 603 template<typename _Mutex> 604 class scoped_lock<_Mutex> 605 { 606 public: 607 using mutex_type = _Mutex; 608 609 explicit scoped_lock(mutex_type& __m) : _M_device(__m) 610 { _M_device.lock(); } 611 612 explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept 613 : _M_device(__m) 614 { } // calling thread owns mutex 615 616 ~scoped_lock() 617 { _M_device.unlock(); } 618 619 scoped_lock(const scoped_lock&) = delete; 620 scoped_lock& operator=(const scoped_lock&) = delete; 621 622 private: 623 mutex_type& _M_device; 624 }; 625#endif // C++17 626 627#ifdef _GLIBCXX_HAS_GTHREADS 628 /// once_flag 629 struct once_flag 630 { 631 private: 632 typedef __gthread_once_t __native_type; 633 __native_type _M_once = __GTHREAD_ONCE_INIT; 634 635 public: 636 /// Constructor 637 constexpr once_flag() noexcept = default; 638 639 /// Deleted copy constructor 640 once_flag(const once_flag&) = delete; 641 /// Deleted assignment operator 642 once_flag& operator=(const once_flag&) = delete; 643 644 template<typename _Callable, typename... _Args> 645 friend void 646 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); 647 }; 648 649#ifdef _GLIBCXX_HAVE_TLS 650 extern __thread void* __once_callable; 651 extern __thread void (*__once_call)(); 652#else 653 extern function<void()> __once_functor; 654 655 extern void 656 __set_once_functor_lock_ptr(unique_lock<mutex>*); 657 658 extern mutex& 659 __get_once_mutex(); 660#endif 661 662 extern "C" void __once_proxy(void); 663 664 /// call_once 665 template<typename _Callable, typename... _Args> 666 void 667 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) 668 { 669 // _GLIBCXX_RESOLVE_LIB_DEFECTS 670 // 2442. call_once() shouldn't DECAY_COPY() 671 auto __callable = [&] { 672 std::__invoke(std::forward<_Callable>(__f), 673 std::forward<_Args>(__args)...); 674 }; 675#ifdef _GLIBCXX_HAVE_TLS 676 __once_callable = std::__addressof(__callable); 677 __once_call = []{ (*(decltype(__callable)*)__once_callable)(); }; 678#else 679 unique_lock<mutex> __functor_lock(__get_once_mutex()); 680 __once_functor = __callable; 681 __set_once_functor_lock_ptr(&__functor_lock); 682#endif 683 684 int __e = __gthread_once(&__once._M_once, &__once_proxy); 685 686#ifndef _GLIBCXX_HAVE_TLS 687 if (__functor_lock) 688 __set_once_functor_lock_ptr(0); 689#endif 690 691#ifdef __clang_analyzer__ 692 // PR libstdc++/82481 693 __once_callable = nullptr; 694 __once_call = nullptr; 695#endif 696 697 if (__e) 698 __throw_system_error(__e); 699 } 700#endif // _GLIBCXX_HAS_GTHREADS 701 702 // @} group mutexes 703_GLIBCXX_END_NAMESPACE_VERSION 704} // namespace 705#endif // _GLIBCXX_USE_C99_STDINT_TR1 706 707#endif // C++11 708 709#endif // _GLIBCXX_MUTEX 710