Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libstdc++-v3 / include / std / mutex
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
50 namespace 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 __try_lock_for_impl(__rtime); }
241
242     template <class _Clock, class _Duration>
243       bool
244       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
245       {
246         chrono::time_point<_Clock, chrono::seconds> __s =
247           chrono::time_point_cast<chrono::seconds>(__atime);
248
249         chrono::nanoseconds __ns =
250           chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
251
252         __gthread_time_t __ts = {
253           static_cast<std::time_t>(__s.time_since_epoch().count()),
254           static_cast<long>(__ns.count())
255         };
256
257         return !__gthread_mutex_timedlock(&_M_mutex, &__ts);
258       }
259
260     void
261     unlock()
262     {
263       // XXX EINVAL, EAGAIN, EBUSY
264       __gthread_mutex_unlock(&_M_mutex);
265     }
266
267     native_handle_type
268     native_handle()
269     { return &_M_mutex; }
270
271   private:
272     template<typename _Rep, typename _Period>
273       typename enable_if<
274         ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
275       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
276       {
277         __clock_t::time_point __atime = __clock_t::now()
278           + chrono::duration_cast<__clock_t::duration>(__rtime);
279
280         return try_lock_until(__atime);
281       }
282
283     template <typename _Rep, typename _Period>
284       typename enable_if<
285         !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
286       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
287       {
288         __clock_t::time_point __atime = __clock_t::now()
289           + ++chrono::duration_cast<__clock_t::duration>(__rtime);
290
291         return try_lock_until(__atime);
292       }
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 __try_lock_for_impl(__rtime); }
334
335     template <class _Clock, class _Duration>
336       bool
337       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
338       {
339         chrono::time_point<_Clock, chrono::seconds>  __s =
340           chrono::time_point_cast<chrono::seconds>(__atime);
341
342         chrono::nanoseconds __ns =
343           chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
344
345         __gthread_time_t __ts = {
346           static_cast<std::time_t>(__s.time_since_epoch().count()),
347           static_cast<long>(__ns.count())
348         };
349
350         return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts);
351       }
352
353     void
354     unlock()
355     {
356       // XXX EINVAL, EAGAIN, EBUSY
357       __gthread_recursive_mutex_unlock(&_M_mutex);
358     }
359
360     native_handle_type
361     native_handle()
362     { return &_M_mutex; }
363
364   private:
365     template<typename _Rep, typename _Period>
366       typename enable_if<
367         ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
368       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
369       {
370         __clock_t::time_point __atime = __clock_t::now()
371           + chrono::duration_cast<__clock_t::duration>(__rtime);
372
373         return try_lock_until(__atime);
374       }
375
376     template <typename _Rep, typename _Period>
377       typename enable_if<
378         !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
379       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
380       {
381         __clock_t::time_point __atime = __clock_t::now()
382           + ++chrono::duration_cast<__clock_t::duration>(__rtime);
383
384         return try_lock_until(__atime);
385       }
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