1 // <mutex> -*- C++ -*- 2 3 // Copyright (C) 2003-2013 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/functexcept.h> 45 #include <bits/gthr.h> 46 #include <bits/move.h> // for std::swap 47 48 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 49 50 namespace std _GLIBCXX_VISIBILITY(default) 51 { 52 _GLIBCXX_BEGIN_NAMESPACE_VERSION 53 54 // Common base class for std::mutex and std::timed_mutex 55 class __mutex_base 56 { 57 protected: 58 typedef __gthread_mutex_t __native_type; 59 60 #ifdef __GTHREAD_MUTEX_INIT 61 __native_type _M_mutex = __GTHREAD_MUTEX_INIT; 62 63 constexpr __mutex_base() noexcept = default; 64 #else 65 __native_type _M_mutex; 66 67 __mutex_base() noexcept 68 { 69 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) 70 __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); 71 } 72 73 ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); } 74 #endif 75 76 __mutex_base(const __mutex_base&) = delete; 77 __mutex_base& operator=(const __mutex_base&) = delete; 78 }; 79 80 // Common base class for std::recursive_mutex and std::timed_recursive_mutex 81 class __recursive_mutex_base 82 { 83 protected: 84 typedef __gthread_recursive_mutex_t __native_type; 85 86 __recursive_mutex_base(const __recursive_mutex_base&) = delete; 87 __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; 88 89 #ifdef __GTHREAD_RECURSIVE_MUTEX_INIT 90 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT; 91 92 __recursive_mutex_base() = default; 93 #else 94 __native_type _M_mutex; 95 96 __recursive_mutex_base() 97 { 98 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) 99 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); 100 } 101 102 ~__recursive_mutex_base() 103 { __gthread_recursive_mutex_destroy(&_M_mutex); } 104 #endif 105 }; 106 107 /** 108 * @defgroup mutexes Mutexes 109 * @ingroup concurrency 110 * 111 * Classes for mutex support. 112 * @{ 113 */ 114 115 /// mutex 116 class mutex : private __mutex_base 117 { 118 public: 119 typedef __native_type* native_handle_type; 120 121 #ifdef __GTHREAD_MUTEX_INIT 122 constexpr 123 #endif 124 mutex() noexcept = default; 125 ~mutex() = default; 126 127 mutex(const mutex&) = delete; 128 mutex& operator=(const mutex&) = delete; 129 130 void 131 lock() 132 { 133 int __e = __gthread_mutex_lock(&_M_mutex); 134 135 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 136 if (__e) 137 __throw_system_error(__e); 138 } 139 140 bool 141 try_lock() noexcept 142 { 143 // XXX EINVAL, EAGAIN, EBUSY 144 return !__gthread_mutex_trylock(&_M_mutex); 145 } 146 147 void 148 unlock() 149 { 150 // XXX EINVAL, EAGAIN, EPERM 151 __gthread_mutex_unlock(&_M_mutex); 152 } 153 154 native_handle_type 155 native_handle() 156 { return &_M_mutex; } 157 }; 158 159 /// recursive_mutex 160 class recursive_mutex : private __recursive_mutex_base 161 { 162 public: 163 typedef __native_type* native_handle_type; 164 165 recursive_mutex() = default; 166 ~recursive_mutex() = default; 167 168 recursive_mutex(const recursive_mutex&) = delete; 169 recursive_mutex& operator=(const recursive_mutex&) = delete; 170 171 void 172 lock() 173 { 174 int __e = __gthread_recursive_mutex_lock(&_M_mutex); 175 176 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 177 if (__e) 178 __throw_system_error(__e); 179 } 180 181 bool 182 try_lock() noexcept 183 { 184 // XXX EINVAL, EAGAIN, EBUSY 185 return !__gthread_recursive_mutex_trylock(&_M_mutex); 186 } 187 188 void 189 unlock() 190 { 191 // XXX EINVAL, EAGAIN, EBUSY 192 __gthread_recursive_mutex_unlock(&_M_mutex); 193 } 194 195 native_handle_type 196 native_handle() 197 { return &_M_mutex; } 198 }; 199 200 #if _GTHREAD_USE_MUTEX_TIMEDLOCK 201 /// timed_mutex 202 class timed_mutex : private __mutex_base 203 { 204 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC 205 typedef chrono::steady_clock __clock_t; 206 #else 207 typedef chrono::high_resolution_clock __clock_t; 208 #endif 209 210 public: 211 typedef __native_type* native_handle_type; 212 213 timed_mutex() = default; 214 ~timed_mutex() = default; 215 216 timed_mutex(const timed_mutex&) = delete; 217 timed_mutex& operator=(const timed_mutex&) = delete; 218 219 void 220 lock() 221 { 222 int __e = __gthread_mutex_lock(&_M_mutex); 223 224 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 225 if (__e) 226 __throw_system_error(__e); 227 } 228 229 bool 230 try_lock() noexcept 231 { 232 // XXX EINVAL, EAGAIN, EBUSY 233 return !__gthread_mutex_trylock(&_M_mutex); 234 } 235 236 template <class _Rep, class _Period> 237 bool 238 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 239 { return __try_lock_for_impl(__rtime); } 240 241 template <class _Clock, class _Duration> 242 bool 243 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 244 { 245 chrono::time_point<_Clock, chrono::seconds> __s = 246 chrono::time_point_cast<chrono::seconds>(__atime); 247 248 chrono::nanoseconds __ns = 249 chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 250 251 __gthread_time_t __ts = { 252 static_cast<std::time_t>(__s.time_since_epoch().count()), 253 static_cast<long>(__ns.count()) 254 }; 255 256 return !__gthread_mutex_timedlock(&_M_mutex, &__ts); 257 } 258 259 void 260 unlock() 261 { 262 // XXX EINVAL, EAGAIN, EBUSY 263 __gthread_mutex_unlock(&_M_mutex); 264 } 265 266 native_handle_type 267 native_handle() 268 { return &_M_mutex; } 269 270 private: 271 template<typename _Rep, typename _Period> 272 typename enable_if< 273 ratio_less_equal<__clock_t::period, _Period>::value, bool>::type 274 __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime) 275 { 276 __clock_t::time_point __atime = __clock_t::now() 277 + chrono::duration_cast<__clock_t::duration>(__rtime); 278 279 return try_lock_until(__atime); 280 } 281 282 template <typename _Rep, typename _Period> 283 typename enable_if< 284 !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type 285 __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime) 286 { 287 __clock_t::time_point __atime = __clock_t::now() 288 + ++chrono::duration_cast<__clock_t::duration>(__rtime); 289 290 return try_lock_until(__atime); 291 } 292 }; 293 294 /// recursive_timed_mutex 295 class recursive_timed_mutex : private __recursive_mutex_base 296 { 297 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC 298 typedef chrono::steady_clock __clock_t; 299 #else 300 typedef chrono::high_resolution_clock __clock_t; 301 #endif 302 303 public: 304 typedef __native_type* native_handle_type; 305 306 recursive_timed_mutex() = default; 307 ~recursive_timed_mutex() = default; 308 309 recursive_timed_mutex(const recursive_timed_mutex&) = delete; 310 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; 311 312 void 313 lock() 314 { 315 int __e = __gthread_recursive_mutex_lock(&_M_mutex); 316 317 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) 318 if (__e) 319 __throw_system_error(__e); 320 } 321 322 bool 323 try_lock() noexcept 324 { 325 // XXX EINVAL, EAGAIN, EBUSY 326 return !__gthread_recursive_mutex_trylock(&_M_mutex); 327 } 328 329 template <class _Rep, class _Period> 330 bool 331 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 332 { return __try_lock_for_impl(__rtime); } 333 334 template <class _Clock, class _Duration> 335 bool 336 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 337 { 338 chrono::time_point<_Clock, chrono::seconds> __s = 339 chrono::time_point_cast<chrono::seconds>(__atime); 340 341 chrono::nanoseconds __ns = 342 chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 343 344 __gthread_time_t __ts = { 345 static_cast<std::time_t>(__s.time_since_epoch().count()), 346 static_cast<long>(__ns.count()) 347 }; 348 349 return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); 350 } 351 352 void 353 unlock() 354 { 355 // XXX EINVAL, EAGAIN, EBUSY 356 __gthread_recursive_mutex_unlock(&_M_mutex); 357 } 358 359 native_handle_type 360 native_handle() 361 { return &_M_mutex; } 362 363 private: 364 template<typename _Rep, typename _Period> 365 typename enable_if< 366 ratio_less_equal<__clock_t::period, _Period>::value, bool>::type 367 __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime) 368 { 369 __clock_t::time_point __atime = __clock_t::now() 370 + chrono::duration_cast<__clock_t::duration>(__rtime); 371 372 return try_lock_until(__atime); 373 } 374 375 template <typename _Rep, typename _Period> 376 typename enable_if< 377 !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type 378 __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime) 379 { 380 __clock_t::time_point __atime = __clock_t::now() 381 + ++chrono::duration_cast<__clock_t::duration>(__rtime); 382 383 return try_lock_until(__atime); 384 } 385 }; 386 #endif 387 388 /// Do not acquire ownership of the mutex. 389 struct defer_lock_t { }; 390 391 /// Try to acquire ownership of the mutex without blocking. 392 struct try_to_lock_t { }; 393 394 /// Assume the calling thread has already obtained mutex ownership 395 /// and manage it. 396 struct adopt_lock_t { }; 397 398 constexpr defer_lock_t defer_lock { }; 399 constexpr try_to_lock_t try_to_lock { }; 400 constexpr adopt_lock_t adopt_lock { }; 401 402 /// @brief Scoped lock idiom. 403 // Acquire the mutex here with a constructor call, then release with 404 // the destructor call in accordance with RAII style. 405 template<typename _Mutex> 406 class lock_guard 407 { 408 public: 409 typedef _Mutex mutex_type; 410 411 explicit lock_guard(mutex_type& __m) : _M_device(__m) 412 { _M_device.lock(); } 413 414 lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m) 415 { } // calling thread owns mutex 416 417 ~lock_guard() 418 { _M_device.unlock(); } 419 420 lock_guard(const lock_guard&) = delete; 421 lock_guard& operator=(const lock_guard&) = delete; 422 423 private: 424 mutex_type& _M_device; 425 }; 426 427 /// unique_lock 428 template<typename _Mutex> 429 class unique_lock 430 { 431 public: 432 typedef _Mutex mutex_type; 433 434 unique_lock() noexcept 435 : _M_device(0), _M_owns(false) 436 { } 437 438 explicit unique_lock(mutex_type& __m) 439 : _M_device(&__m), _M_owns(false) 440 { 441 lock(); 442 _M_owns = true; 443 } 444 445 unique_lock(mutex_type& __m, defer_lock_t) noexcept 446 : _M_device(&__m), _M_owns(false) 447 { } 448 449 unique_lock(mutex_type& __m, try_to_lock_t) 450 : _M_device(&__m), _M_owns(_M_device->try_lock()) 451 { } 452 453 unique_lock(mutex_type& __m, adopt_lock_t) 454 : _M_device(&__m), _M_owns(true) 455 { 456 // XXX calling thread owns mutex 457 } 458 459 template<typename _Clock, typename _Duration> 460 unique_lock(mutex_type& __m, 461 const chrono::time_point<_Clock, _Duration>& __atime) 462 : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime)) 463 { } 464 465 template<typename _Rep, typename _Period> 466 unique_lock(mutex_type& __m, 467 const chrono::duration<_Rep, _Period>& __rtime) 468 : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime)) 469 { } 470 471 ~unique_lock() 472 { 473 if (_M_owns) 474 unlock(); 475 } 476 477 unique_lock(const unique_lock&) = delete; 478 unique_lock& operator=(const unique_lock&) = delete; 479 480 unique_lock(unique_lock&& __u) noexcept 481 : _M_device(__u._M_device), _M_owns(__u._M_owns) 482 { 483 __u._M_device = 0; 484 __u._M_owns = false; 485 } 486 487 unique_lock& operator=(unique_lock&& __u) noexcept 488 { 489 if(_M_owns) 490 unlock(); 491 492 unique_lock(std::move(__u)).swap(*this); 493 494 __u._M_device = 0; 495 __u._M_owns = false; 496 497 return *this; 498 } 499 500 void 501 lock() 502 { 503 if (!_M_device) 504 __throw_system_error(int(errc::operation_not_permitted)); 505 else if (_M_owns) 506 __throw_system_error(int(errc::resource_deadlock_would_occur)); 507 else 508 { 509 _M_device->lock(); 510 _M_owns = true; 511 } 512 } 513 514 bool 515 try_lock() 516 { 517 if (!_M_device) 518 __throw_system_error(int(errc::operation_not_permitted)); 519 else if (_M_owns) 520 __throw_system_error(int(errc::resource_deadlock_would_occur)); 521 else 522 { 523 _M_owns = _M_device->try_lock(); 524 return _M_owns; 525 } 526 } 527 528 template<typename _Clock, typename _Duration> 529 bool 530 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) 531 { 532 if (!_M_device) 533 __throw_system_error(int(errc::operation_not_permitted)); 534 else if (_M_owns) 535 __throw_system_error(int(errc::resource_deadlock_would_occur)); 536 else 537 { 538 _M_owns = _M_device->try_lock_until(__atime); 539 return _M_owns; 540 } 541 } 542 543 template<typename _Rep, typename _Period> 544 bool 545 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) 546 { 547 if (!_M_device) 548 __throw_system_error(int(errc::operation_not_permitted)); 549 else if (_M_owns) 550 __throw_system_error(int(errc::resource_deadlock_would_occur)); 551 else 552 { 553 _M_owns = _M_device->try_lock_for(__rtime); 554 return _M_owns; 555 } 556 } 557 558 void 559 unlock() 560 { 561 if (!_M_owns) 562 __throw_system_error(int(errc::operation_not_permitted)); 563 else if (_M_device) 564 { 565 _M_device->unlock(); 566 _M_owns = false; 567 } 568 } 569 570 void 571 swap(unique_lock& __u) noexcept 572 { 573 std::swap(_M_device, __u._M_device); 574 std::swap(_M_owns, __u._M_owns); 575 } 576 577 mutex_type* 578 release() noexcept 579 { 580 mutex_type* __ret = _M_device; 581 _M_device = 0; 582 _M_owns = false; 583 return __ret; 584 } 585 586 bool 587 owns_lock() const noexcept 588 { return _M_owns; } 589 590 explicit operator bool() const noexcept 591 { return owns_lock(); } 592 593 mutex_type* 594 mutex() const noexcept 595 { return _M_device; } 596 597 private: 598 mutex_type* _M_device; 599 bool _M_owns; // XXX use atomic_bool 600 }; 601 602 /// Partial specialization for unique_lock objects. 603 template<typename _Mutex> 604 inline void 605 swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept 606 { __x.swap(__y); } 607 608 template<int _Idx> 609 struct __unlock_impl 610 { 611 template<typename... _Lock> 612 static void 613 __do_unlock(tuple<_Lock&...>& __locks) 614 { 615 std::get<_Idx>(__locks).unlock(); 616 __unlock_impl<_Idx - 1>::__do_unlock(__locks); 617 } 618 }; 619 620 template<> 621 struct __unlock_impl<-1> 622 { 623 template<typename... _Lock> 624 static void 625 __do_unlock(tuple<_Lock&...>&) 626 { } 627 }; 628 629 template<typename _Lock> 630 unique_lock<_Lock> 631 __try_to_lock(_Lock& __l) 632 { return unique_lock<_Lock>(__l, try_to_lock); } 633 634 template<int _Idx, bool _Continue = true> 635 struct __try_lock_impl 636 { 637 template<typename... _Lock> 638 static void 639 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 640 { 641 __idx = _Idx; 642 auto __lock = __try_to_lock(std::get<_Idx>(__locks)); 643 if (__lock.owns_lock()) 644 { 645 __try_lock_impl<_Idx + 1, _Idx + 2 < sizeof...(_Lock)>:: 646 __do_try_lock(__locks, __idx); 647 if (__idx == -1) 648 __lock.release(); 649 } 650 } 651 }; 652 653 template<int _Idx> 654 struct __try_lock_impl<_Idx, false> 655 { 656 template<typename... _Lock> 657 static void 658 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) 659 { 660 __idx = _Idx; 661 auto __lock = __try_to_lock(std::get<_Idx>(__locks)); 662 if (__lock.owns_lock()) 663 { 664 __idx = -1; 665 __lock.release(); 666 } 667 } 668 }; 669 670 /** @brief Generic try_lock. 671 * @param __l1 Meets Mutex requirements (try_lock() may throw). 672 * @param __l2 Meets Mutex requirements (try_lock() may throw). 673 * @param __l3 Meets Mutex requirements (try_lock() may throw). 674 * @return Returns -1 if all try_lock() calls return true. Otherwise returns 675 * a 0-based index corresponding to the argument that returned false. 676 * @post Either all arguments are locked, or none will be. 677 * 678 * Sequentially calls try_lock() on each argument. 679 */ 680 template<typename _Lock1, typename _Lock2, typename... _Lock3> 681 int 682 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3) 683 { 684 int __idx; 685 auto __locks = std::tie(__l1, __l2, __l3...); 686 __try 687 { __try_lock_impl<0>::__do_try_lock(__locks, __idx); } 688 __catch(...) 689 { } 690 return __idx; 691 } 692 693 /** @brief Generic lock. 694 * @param __l1 Meets Mutex requirements (try_lock() may throw). 695 * @param __l2 Meets Mutex requirements (try_lock() may throw). 696 * @param __l3 Meets Mutex requirements (try_lock() may throw). 697 * @throw An exception thrown by an argument's lock() or try_lock() member. 698 * @post All arguments are locked. 699 * 700 * All arguments are locked via a sequence of calls to lock(), try_lock() 701 * and unlock(). If the call exits via an exception any locks that were 702 * obtained will be released. 703 */ 704 template<typename _L1, typename _L2, typename ..._L3> 705 void 706 lock(_L1& __l1, _L2& __l2, _L3&... __l3) 707 { 708 while (true) 709 { 710 unique_lock<_L1> __first(__l1); 711 int __idx; 712 auto __locks = std::tie(__l2, __l3...); 713 __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx); 714 if (__idx == -1) 715 { 716 __first.release(); 717 return; 718 } 719 } 720 } 721 722 /// once_flag 723 struct once_flag 724 { 725 private: 726 typedef __gthread_once_t __native_type; 727 __native_type _M_once = __GTHREAD_ONCE_INIT; 728 729 public: 730 /// Constructor 731 constexpr once_flag() noexcept = default; 732 733 /// Deleted copy constructor 734 once_flag(const once_flag&) = delete; 735 /// Deleted assignment operator 736 once_flag& operator=(const once_flag&) = delete; 737 738 template<typename _Callable, typename... _Args> 739 friend void 740 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); 741 }; 742 743 #ifdef _GLIBCXX_HAVE_TLS 744 extern __thread void* __once_callable; 745 extern __thread void (*__once_call)(); 746 747 template<typename _Callable> 748 inline void 749 __once_call_impl() 750 { 751 (*(_Callable*)__once_callable)(); 752 } 753 #else 754 extern function<void()> __once_functor; 755 756 extern void 757 __set_once_functor_lock_ptr(unique_lock<mutex>*); 758 759 extern mutex& 760 __get_once_mutex(); 761 #endif 762 763 extern "C" void __once_proxy(void); 764 765 /// call_once 766 template<typename _Callable, typename... _Args> 767 void 768 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) 769 { 770 #ifdef _GLIBCXX_HAVE_TLS 771 auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f), 772 std::forward<_Args>(__args)...); 773 __once_callable = &__bound_functor; 774 __once_call = &__once_call_impl<decltype(__bound_functor)>; 775 #else 776 unique_lock<mutex> __functor_lock(__get_once_mutex()); 777 auto __callable = std::__bind_simple(std::forward<_Callable>(__f), 778 std::forward<_Args>(__args)...); 779 __once_functor = [&]() { __callable(); }; 780 __set_once_functor_lock_ptr(&__functor_lock); 781 #endif 782 783 int __e = __gthread_once(&(__once._M_once), &__once_proxy); 784 785 #ifndef _GLIBCXX_HAVE_TLS 786 if (__functor_lock) 787 __set_once_functor_lock_ptr(0); 788 #endif 789 790 if (__e) 791 __throw_system_error(__e); 792 } 793 794 // @} group mutexes 795 _GLIBCXX_END_NAMESPACE_VERSION 796 } // namespace 797 798 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 799 800 #endif // C++11 801 802 #endif // _GLIBCXX_MUTEX 803