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