1// <mutex> -*- C++ -*- 2 3// Copyright (C) 2003-2016 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 <functional> 43#include <system_error> 44#include <bits/std_mutex.h> 45#if ! _GTHREAD_USE_MUTEX_TIMEDLOCK 46# include <condition_variable> 47# include <thread> 48#endif 49 50#ifdef _GLIBCXX_USE_C99_STDINT_TR1 51 52namespace std _GLIBCXX_VISIBILITY(default) 53{ 54_GLIBCXX_BEGIN_NAMESPACE_VERSION 55 56 /** 57 * @ingroup mutexes 58 * @{ 59 */ 60 61#ifdef _GLIBCXX_HAS_GTHREADS 62 63 // Common base class for std::recursive_mutex and std::recursive_timed_mutex 64 class __recursive_mutex_base 65 { 66 protected: 67 typedef __gthread_recursive_mutex_t __native_type; 68 69 __recursive_mutex_base(const __recursive_mutex_base&) = delete; 70 __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; 71 72#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT 73 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT; 74 75 __recursive_mutex_base() = default; 76#else 77 __native_type _M_mutex; 78 79 __recursive_mutex_base() 80 { 81 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) 82 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); 83 } 84 85 ~__recursive_mutex_base() 86 { __gthread_recursive_mutex_destroy(&_M_mutex); } 87#endif 88 }; 89 90 /// The standard recursive mutex type. 91 class recursive_mutex : private __recursive_mutex_base 92 { 93 public: 94 typedef __native_type* native_handle_type; 95 96 recursive_mutex() = default; 97 ~recursive_mutex() = default; 98 99 recursive_mutex(const recursive_mutex&) = delete; 100 recursive_mutex& operator=(const recursive_mutex&) = delete; 101 102 void 103 lock() 104 { 105 int __e = __gthread_recursive_mutex_lock(&_M_mutex); 106 107 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 108 if (__e) 109 __throw_system_error(__e); 110 } 111 112 bool 113 try_lock() noexcept 114 { 115 // XXX EINVAL, EAGAIN, EBUSY 116 return !__gthread_recursive_mutex_trylock(&_M_mutex); 117 } 118 119 void 120 unlock() 121 { 122 // XXX EINVAL, EAGAIN, EBUSY 123 __gthread_recursive_mutex_unlock(&_M_mutex); 124 } 125 126 native_handle_type 127 native_handle() 128 { return &_M_mutex; } 129 }; 130 131#if _GTHREAD_USE_MUTEX_TIMEDLOCK 132 template<typename _Derived> 133 class __timed_mutex_impl 134 { 135 protected: 136 typedef chrono::high_resolution_clock __clock_t; 137 138 template<typename _Rep, typename _Period> 139 bool 140 _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 141 { 142 using chrono::steady_clock; 143 auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime); 144 if (ratio_greater<steady_clock::period, _Period>()) 145 ++__rt; 146 return _M_try_lock_until(steady_clock::now() + __rt); 147 } 148 149 template<typename _Duration> 150 bool 151 _M_try_lock_until(const chrono::time_point<__clock_t, 152 _Duration>& __atime) 153 { 154 auto __s = chrono::time_point_cast<chrono::seconds>(__atime); 155 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 156 157 __gthread_time_t __ts = { 158 static_cast<std::time_t>(__s.time_since_epoch().count()), 159 static_cast<long>(__ns.count()) 160 }; 161 162 return static_cast<_Derived*>(this)->_M_timedlock(__ts); 163 } 164 165 template<typename _Clock, typename _Duration> 166 bool 167 _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 168 { 169 auto __rtime = __atime - _Clock::now(); 170 return _M_try_lock_until(__clock_t::now() + __rtime); 171 } 172 }; 173 174 /// The standard timed mutex type. 175 class timed_mutex 176 : private __mutex_base, public __timed_mutex_impl<timed_mutex> 177 { 178 public: 179 typedef __native_type* native_handle_type; 180 181 timed_mutex() = default; 182 ~timed_mutex() = default; 183 184 timed_mutex(const timed_mutex&) = delete; 185 timed_mutex& operator=(const timed_mutex&) = delete; 186 187 void 188 lock() 189 { 190 int __e = __gthread_mutex_lock(&_M_mutex); 191 192 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 193 if (__e) 194 __throw_system_error(__e); 195 } 196 197 bool 198 try_lock() noexcept 199 { 200 // XXX EINVAL, EAGAIN, EBUSY 201 return !__gthread_mutex_trylock(&_M_mutex); 202 } 203 204 template <class _Rep, class _Period> 205 bool 206 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 207 { return _M_try_lock_for(__rtime); } 208 209 template <class _Clock, class _Duration> 210 bool 211 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 212 { return _M_try_lock_until(__atime); } 213 214 void 215 unlock() 216 { 217 // XXX EINVAL, EAGAIN, EBUSY 218 __gthread_mutex_unlock(&_M_mutex); 219 } 220 221 native_handle_type 222 native_handle() 223 { return &_M_mutex; } 224 225 private: 226 friend class __timed_mutex_impl<timed_mutex>; 227 228 bool 229 _M_timedlock(const __gthread_time_t& __ts) 230 { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); } 231 }; 232 233 /// recursive_timed_mutex 234 class recursive_timed_mutex 235 : private __recursive_mutex_base, 236 public __timed_mutex_impl<recursive_timed_mutex> 237 { 238 public: 239 typedef __native_type* native_handle_type; 240 241 recursive_timed_mutex() = default; 242 ~recursive_timed_mutex() = default; 243 244 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 245 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 246 247 void 248 lock() 249 { 250 int __e = __gthread_recursive_mutex_lock(&_M_mutex); 251 252 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 253 if (__e) 254 __throw_system_error(__e); 255 } 256 257 bool 258 try_lock() noexcept 259 { 260 // XXX EINVAL, EAGAIN, EBUSY 261 return !__gthread_recursive_mutex_trylock(&_M_mutex); 262 } 263 264 template <class _Rep, class _Period> 265 bool 266 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 267 { return _M_try_lock_for(__rtime); } 268 269 template <class _Clock, class _Duration> 270 bool 271 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 272 { return _M_try_lock_until(__atime); } 273 274 void 275 unlock() 276 { 277 // XXX EINVAL, EAGAIN, EBUSY 278 __gthread_recursive_mutex_unlock(&_M_mutex); 279 } 280 281 native_handle_type 282 native_handle() 283 { return &_M_mutex; } 284 285 private: 286 friend class __timed_mutex_impl<recursive_timed_mutex>; 287 288 bool 289 _M_timedlock(const __gthread_time_t& __ts) 290 { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); } 291 }; 292 293#else // !_GTHREAD_USE_MUTEX_TIMEDLOCK 294 295 /// timed_mutex 296 class timed_mutex 297 { 298 mutex _M_mut; 299 condition_variable _M_cv; 300 bool _M_locked = false; 301 302 public: 303 304 timed_mutex() = default; 305 ~timed_mutex() { __glibcxx_assert( !_M_locked ); } 306 307 timed_mutex(const timed_mutex&) = delete; 308 timed_mutex& operator=(const timed_mutex&) = delete; 309 310 void 311 lock() 312 { 313 unique_lock<mutex> __lk(_M_mut); 314 _M_cv.wait(__lk, [&]{ return !_M_locked; }); 315 _M_locked = true; 316 } 317 318 bool 319 try_lock() 320 { 321 lock_guard<mutex> __lk(_M_mut); 322 if (_M_locked) 323 return false; 324 _M_locked = true; 325 return true; 326 } 327 328 template<typename _Rep, typename _Period> 329 bool 330 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 331 { 332 unique_lock<mutex> __lk(_M_mut); 333 if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; })) 334 return false; 335 _M_locked = true; 336 return true; 337 } 338 339 template<typename _Clock, typename _Duration> 340 bool 341 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 342 { 343 unique_lock<mutex> __lk(_M_mut); 344 if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; })) 345 return false; 346 _M_locked = true; 347 return true; 348 } 349 350 void 351 unlock() 352 { 353 lock_guard<mutex> __lk(_M_mut); 354 __glibcxx_assert( _M_locked ); 355 _M_locked = false; 356 _M_cv.notify_one(); 357 } 358 }; 359 360 /// recursive_timed_mutex 361 class recursive_timed_mutex 362 { 363 mutex _M_mut; 364 condition_variable _M_cv; 365 thread::id _M_owner; 366 unsigned _M_count = 0; 367 368 // Predicate type that tests whether the current thread can lock a mutex. 369 struct _Can_lock 370 { 371 // Returns true if the mutex is unlocked or is locked by _M_caller. 372 bool 373 operator()() const noexcept 374 { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; } 375 376 const recursive_timed_mutex* _M_mx; 377 thread::id _M_caller; 378 }; 379 380 public: 381 382 recursive_timed_mutex() = default; 383 ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); } 384 385 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 386 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 387 388 void 389 lock() 390 { 391 auto __id = this_thread::get_id(); 392 _Can_lock __can_lock{this, __id}; 393 unique_lock<mutex> __lk(_M_mut); 394 _M_cv.wait(__lk, __can_lock); 395 if (_M_count == -1u) 396 __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3 397 _M_owner = __id; 398 ++_M_count; 399 } 400 401 bool 402 try_lock() 403 { 404 auto __id = this_thread::get_id(); 405 _Can_lock __can_lock{this, __id}; 406 lock_guard<mutex> __lk(_M_mut); 407 if (!__can_lock()) 408 return false; 409 if (_M_count == -1u) 410 return false; 411 _M_owner = __id; 412 ++_M_count; 413 return true; 414 } 415 416 template<typename _Rep, typename _Period> 417 bool 418 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 419 { 420 auto __id = this_thread::get_id(); 421 _Can_lock __can_lock{this, __id}; 422 unique_lock<mutex> __lk(_M_mut); 423 if (!_M_cv.wait_for(__lk, __rtime, __can_lock)) 424 return false; 425 if (_M_count == -1u) 426 return false; 427 _M_owner = __id; 428 ++_M_count; 429 return true; 430 } 431 432 template<typename _Clock, typename _Duration> 433 bool 434 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 435 { 436 auto __id = this_thread::get_id(); 437 _Can_lock __can_lock{this, __id}; 438 unique_lock<mutex> __lk(_M_mut); 439 if (!_M_cv.wait_until(__lk, __atime, __can_lock)) 440 return false; 441 if (_M_count == -1u) 442 return false; 443 _M_owner = __id; 444 ++_M_count; 445 return true; 446 } 447 448 void 449 unlock() 450 { 451 lock_guard<mutex> __lk(_M_mut); 452 __glibcxx_assert( _M_owner == this_thread::get_id() ); 453 __glibcxx_assert( _M_count > 0 ); 454 if (--_M_count == 0) 455 { 456 _M_owner = {}; 457 _M_cv.notify_one(); 458 } 459 } 460 }; 461 462#endif 463#endif // _GLIBCXX_HAS_GTHREADS 464 465 template<typename _Lock> 466 inline unique_lock<_Lock> 467 __try_to_lock(_Lock& __l) 468 { return unique_lock<_Lock>{__l, try_to_lock}; } 469 470 template<int _Idx, bool _Continue = true> 471 struct __try_lock_impl 472 { 473 template<typename... _Lock> 474 static void 475 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 476 { 477 __idx = _Idx; 478 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); 479 if (__lock.owns_lock()) 480 { 481 constexpr bool __cont = _Idx + 2 < sizeof...(_Lock); 482 using __try_locker = __try_lock_impl<_Idx + 1, __cont>; 483 __try_locker::__do_try_lock(__locks, __idx); 484 if (__idx == -1) 485 __lock.release(); 486 } 487 } 488 }; 489 490 template<int _Idx> 491 struct __try_lock_impl<_Idx, false> 492 { 493 template<typename... _Lock> 494 static void 495 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 496 { 497 __idx = _Idx; 498 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); 499 if (__lock.owns_lock()) 500 { 501 __idx = -1; 502 __lock.release(); 503 } 504 } 505 }; 506 507 /** @brief Generic try_lock. 508 * @param __l1 Meets Mutex requirements (try_lock() may throw). 509 * @param __l2 Meets Mutex requirements (try_lock() may throw). 510 * @param __l3 Meets Mutex requirements (try_lock() may throw). 511 * @return Returns -1 if all try_lock() calls return true. Otherwise returns 512 * a 0-based index corresponding to the argument that returned false. 513 * @post Either all arguments are locked, or none will be. 514 * 515 * Sequentially calls try_lock() on each argument. 516 */ 517 template<typename _Lock1, typename _Lock2, typename... _Lock3> 518 int 519 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3) 520 { 521 int __idx; 522 auto __locks = std::tie(__l1, __l2, __l3...); 523 __try_lock_impl<0>::__do_try_lock(__locks, __idx); 524 return __idx; 525 } 526 527 /** @brief Generic lock. 528 * @param __l1 Meets Mutex requirements (try_lock() may throw). 529 * @param __l2 Meets Mutex requirements (try_lock() may throw). 530 * @param __l3 Meets Mutex requirements (try_lock() may throw). 531 * @throw An exception thrown by an argument's lock() or try_lock() member. 532 * @post All arguments are locked. 533 * 534 * All arguments are locked via a sequence of calls to lock(), try_lock() 535 * and unlock(). If the call exits via an exception any locks that were 536 * obtained will be released. 537 */ 538 template<typename _L1, typename _L2, typename... _L3> 539 void 540 lock(_L1& __l1, _L2& __l2, _L3&... __l3) 541 { 542 while (true) 543 { 544 using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>; 545 unique_lock<_L1> __first(__l1); 546 int __idx; 547 auto __locks = std::tie(__l2, __l3...); 548 __try_locker::__do_try_lock(__locks, __idx); 549 if (__idx == -1) 550 { 551 __first.release(); 552 return; 553 } 554 } 555 } 556 557#ifdef _GLIBCXX_HAS_GTHREADS 558 /// once_flag 559 struct once_flag 560 { 561 private: 562 typedef __gthread_once_t __native_type; 563 __native_type _M_once = __GTHREAD_ONCE_INIT; 564 565 public: 566 /// Constructor 567 constexpr once_flag() noexcept = default; 568 569 /// Deleted copy constructor 570 once_flag(const once_flag&) = delete; 571 /// Deleted assignment operator 572 once_flag& operator=(const once_flag&) = delete; 573 574 template<typename _Callable, typename... _Args> 575 friend void 576 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); 577 }; 578 579#ifdef _GLIBCXX_HAVE_TLS 580 extern __thread void* __once_callable; 581 extern __thread void (*__once_call)(); 582#else 583 extern function<void()> __once_functor; 584 585 extern void 586 __set_once_functor_lock_ptr(unique_lock<mutex>*); 587 588 extern mutex& 589 __get_once_mutex(); 590#endif 591 592 extern "C" void __once_proxy(void); 593 594 /// call_once 595 template<typename _Callable, typename... _Args> 596 void 597 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) 598 { 599 // _GLIBCXX_RESOLVE_LIB_DEFECTS 600 // 2442. call_once() shouldn't DECAY_COPY() 601 auto __callable = [&] { 602 std::__invoke(std::forward<_Callable>(__f), 603 std::forward<_Args>(__args)...); 604 }; 605#ifdef _GLIBCXX_HAVE_TLS 606 __once_callable = std::__addressof(__callable); 607 __once_call = []{ (*(decltype(__callable)*)__once_callable)(); }; 608#else 609 unique_lock<mutex> __functor_lock(__get_once_mutex()); 610 __once_functor = __callable; 611 __set_once_functor_lock_ptr(&__functor_lock); 612#endif 613 614 int __e = __gthread_once(&__once._M_once, &__once_proxy); 615 616#ifndef _GLIBCXX_HAVE_TLS 617 if (__functor_lock) 618 __set_once_functor_lock_ptr(0); 619#endif 620 621 if (__e) 622 __throw_system_error(__e); 623 } 624#endif // _GLIBCXX_HAS_GTHREADS 625 626 // @} group mutexes 627_GLIBCXX_END_NAMESPACE_VERSION 628} // namespace 629#endif // _GLIBCXX_USE_C99_STDINT_TR1 630 631#endif // C++11 632 633#endif // _GLIBCXX_MUTEX 634