OSDN Git Service

PR libstdc++/49894
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / std / mutex
1 // <mutex> -*- C++ -*-
2
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 // <http://www.gnu.org/licenses/>.
25
26 /** @file include/mutex
27  *  This is a Standard C++ Library header.
28  */
29
30 #ifndef _GLIBCXX_MUTEX
31 #define _GLIBCXX_MUTEX 1
32
33 #pragma GCC system_header
34
35 #ifndef __GXX_EXPERIMENTAL_CXX0X__
36 # include <bits/c++0x_warning.h>
37 #else
38
39 #include <tuple>
40 #include <chrono>
41 #include <exception>
42 #include <type_traits>
43 #include <functional>
44 #include <system_error>
45 #include <bits/functexcept.h>
46 #include <bits/gthr.h>
47 #include <bits/move.h> // for std::swap
48
49 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
50
51 namespace std _GLIBCXX_VISIBILITY(default)
52 {
53 _GLIBCXX_BEGIN_NAMESPACE_VERSION
54
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() { __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     { _S_destroy(&_M_mutex); }
105
106   private:
107     // FIXME: gthreads doesn't define __gthread_recursive_mutex_destroy
108     // so we need to obtain a __gthread_mutex_t to destroy
109
110     // matches when there's only one mutex type
111     template<typename _Rm>
112       static
113       typename enable_if<is_same<_Rm, __gthread_mutex_t>::value, void>::type
114       _S_destroy(_Rm* __mx)
115       { __gthread_mutex_destroy(__mx); }
116
117     // matches a recursive mutex with a member 'actual'
118     template<typename _Rm>
119       static typename enable_if<sizeof(&_Rm::actual), void>::type
120       _S_destroy(_Rm* __mx)
121       { __gthread_mutex_destroy(&__mx->actual); }
122
123     // matches a gthr-win32.h recursive mutex
124     template<typename _Rm>
125       static typename enable_if<sizeof(&_Rm::sema), void>::type
126       _S_destroy(_Rm* __mx)
127       {
128         __gthread_mutex_t __tmp;
129         _S_destroy_win32(&__tmp, __mx);
130       }
131
132     template<typename _Mx, typename _Rm>
133       static void
134       _S_destroy_win32(_Mx* __mx, _Rm const* __rmx)
135       {
136         __mx->counter = __rmx->counter;
137         __mx->sema = __rmx->sema;
138         __gthread_mutex_destroy(__mx);
139       }
140 #endif
141   };
142
143   /**
144    * @defgroup mutexes Mutexes
145    * @ingroup concurrency
146    *
147    * Classes for mutex support.
148    * @{
149    */
150
151   /// mutex
152   class mutex : private __mutex_base
153   {
154   public:
155     typedef __native_type*                      native_handle_type;
156
157 #ifdef __GTHREAD_MUTEX_INIT
158     constexpr
159 #endif
160     mutex() noexcept = default;
161     ~mutex() = default;
162
163     mutex(const mutex&) = delete;
164     mutex& operator=(const mutex&) = delete;
165
166     void
167     lock()
168     {
169       int __e = __gthread_mutex_lock(&_M_mutex);
170
171       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
172       if (__e)
173         __throw_system_error(__e);
174     }
175
176     bool
177     try_lock() noexcept
178     {
179       // XXX EINVAL, EAGAIN, EBUSY
180       return !__gthread_mutex_trylock(&_M_mutex);
181     }
182
183     void
184     unlock()
185     {
186       // XXX EINVAL, EAGAIN, EPERM
187       __gthread_mutex_unlock(&_M_mutex);
188     }
189
190     native_handle_type
191     native_handle()
192     { return &_M_mutex; }
193   };
194
195   /// recursive_mutex
196   class recursive_mutex : private __recursive_mutex_base
197   {
198   public:
199     typedef __native_type*                      native_handle_type;
200
201     recursive_mutex() = default;
202     ~recursive_mutex() = default;
203
204     recursive_mutex(const recursive_mutex&) = delete;
205     recursive_mutex& operator=(const recursive_mutex&) = delete;
206
207     void
208     lock()
209     {
210       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
211
212       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
213       if (__e)
214         __throw_system_error(__e);
215     }
216
217     bool
218     try_lock() noexcept
219     {
220       // XXX EINVAL, EAGAIN, EBUSY
221       return !__gthread_recursive_mutex_trylock(&_M_mutex);
222     }
223
224     void
225     unlock()
226     {
227       // XXX EINVAL, EAGAIN, EBUSY
228       __gthread_recursive_mutex_unlock(&_M_mutex);
229     }
230
231     native_handle_type
232     native_handle()
233     { return &_M_mutex; }
234   };
235
236 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
237   /// timed_mutex
238   class timed_mutex : private __mutex_base
239   {
240 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
241     typedef chrono::steady_clock                __clock_t;
242 #else
243     typedef chrono::high_resolution_clock       __clock_t;
244 #endif
245
246   public:
247     typedef __native_type*                      native_handle_type;
248
249     timed_mutex() = default;
250     ~timed_mutex() = default;
251
252     timed_mutex(const timed_mutex&) = delete;
253     timed_mutex& operator=(const timed_mutex&) = delete;
254
255     void
256     lock()
257     {
258       int __e = __gthread_mutex_lock(&_M_mutex);
259
260       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
261       if (__e)
262         __throw_system_error(__e);
263     }
264
265     bool
266     try_lock() noexcept
267     {
268       // XXX EINVAL, EAGAIN, EBUSY
269       return !__gthread_mutex_trylock(&_M_mutex);
270     }
271
272     template <class _Rep, class _Period>
273       bool
274       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
275       { return __try_lock_for_impl(__rtime); }
276
277     template <class _Clock, class _Duration>
278       bool
279       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
280       {
281         chrono::time_point<_Clock, chrono::seconds> __s =
282           chrono::time_point_cast<chrono::seconds>(__atime);
283
284         chrono::nanoseconds __ns =
285           chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
286
287         __gthread_time_t __ts = {
288           static_cast<std::time_t>(__s.time_since_epoch().count()),
289           static_cast<long>(__ns.count())
290         };
291
292         return !__gthread_mutex_timedlock(&_M_mutex, &__ts);
293       }
294
295     void
296     unlock()
297     {
298       // XXX EINVAL, EAGAIN, EBUSY
299       __gthread_mutex_unlock(&_M_mutex);
300     }
301
302     native_handle_type
303     native_handle()
304     { return &_M_mutex; }
305
306   private:
307     template<typename _Rep, typename _Period>
308       typename enable_if<
309         ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
310       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
311       {
312         __clock_t::time_point __atime = __clock_t::now()
313           + chrono::duration_cast<__clock_t::duration>(__rtime);
314
315         return try_lock_until(__atime);
316       }
317
318     template <typename _Rep, typename _Period>
319       typename enable_if<
320         !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
321       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
322       {
323         __clock_t::time_point __atime = __clock_t::now()
324           + ++chrono::duration_cast<__clock_t::duration>(__rtime);
325
326         return try_lock_until(__atime);
327       }
328   };
329
330   /// recursive_timed_mutex
331   class recursive_timed_mutex : private __recursive_mutex_base
332   {
333 #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
334     typedef chrono::steady_clock                __clock_t;
335 #else
336     typedef chrono::high_resolution_clock       __clock_t;
337 #endif
338
339   public:
340     typedef __native_type*                      native_handle_type;
341
342     recursive_timed_mutex() = default;
343     ~recursive_timed_mutex() = default;
344
345     recursive_timed_mutex(const recursive_timed_mutex&) = delete;
346     recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
347
348     void
349     lock()
350     {
351       int __e = __gthread_recursive_mutex_lock(&_M_mutex);
352
353       // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
354       if (__e)
355         __throw_system_error(__e);
356     }
357
358     bool
359     try_lock() noexcept
360     {
361       // XXX EINVAL, EAGAIN, EBUSY
362       return !__gthread_recursive_mutex_trylock(&_M_mutex);
363     }
364
365     template <class _Rep, class _Period>
366       bool
367       try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
368       { return __try_lock_for_impl(__rtime); }
369
370     template <class _Clock, class _Duration>
371       bool
372       try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
373       {
374         chrono::time_point<_Clock, chrono::seconds>  __s =
375           chrono::time_point_cast<chrono::seconds>(__atime);
376
377         chrono::nanoseconds __ns =
378           chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
379
380         __gthread_time_t __ts = {
381           static_cast<std::time_t>(__s.time_since_epoch().count()),
382           static_cast<long>(__ns.count())
383         };
384
385         return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts);
386       }
387
388     void
389     unlock()
390     {
391       // XXX EINVAL, EAGAIN, EBUSY
392       __gthread_recursive_mutex_unlock(&_M_mutex);
393     }
394
395     native_handle_type
396     native_handle()
397     { return &_M_mutex; }
398
399   private:
400     template<typename _Rep, typename _Period>
401       typename enable_if<
402         ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
403       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
404       {
405         __clock_t::time_point __atime = __clock_t::now()
406           + chrono::duration_cast<__clock_t::duration>(__rtime);
407
408         return try_lock_until(__atime);
409       }
410
411     template <typename _Rep, typename _Period>
412       typename enable_if<
413         !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type
414       __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime)
415       {
416         __clock_t::time_point __atime = __clock_t::now()
417           + ++chrono::duration_cast<__clock_t::duration>(__rtime);
418
419         return try_lock_until(__atime);
420       }
421   };
422 #endif
423
424   /// Do not acquire ownership of the mutex.
425   struct defer_lock_t { };
426
427   /// Try to acquire ownership of the mutex without blocking.
428   struct try_to_lock_t { };
429
430   /// Assume the calling thread has already obtained mutex ownership
431   /// and manage it.
432   struct adopt_lock_t { };
433
434   constexpr defer_lock_t        defer_lock { };
435   constexpr try_to_lock_t       try_to_lock { };
436   constexpr adopt_lock_t        adopt_lock { };
437
438   /// @brief  Scoped lock idiom.
439   // Acquire the mutex here with a constructor call, then release with
440   // the destructor call in accordance with RAII style.
441   template<typename _Mutex>
442     class lock_guard
443     {
444     public:
445       typedef _Mutex mutex_type;
446
447       explicit lock_guard(mutex_type& __m) : _M_device(__m)
448       { _M_device.lock(); }
449
450       lock_guard(mutex_type& __m, adopt_lock_t) : _M_device(__m)
451       { } // calling thread owns mutex
452
453       ~lock_guard()
454       { _M_device.unlock(); }
455
456       lock_guard(const lock_guard&) = delete;
457       lock_guard& operator=(const lock_guard&) = delete;
458
459     private:
460       mutex_type&  _M_device;
461     };
462
463   /// unique_lock
464   template<typename _Mutex>
465     class unique_lock
466     {
467     public:
468       typedef _Mutex mutex_type;
469
470       unique_lock() noexcept
471       : _M_device(0), _M_owns(false)
472       { }
473
474       explicit unique_lock(mutex_type& __m)
475       : _M_device(&__m), _M_owns(false)
476       {
477         lock();
478         _M_owns = true;
479       }
480
481       unique_lock(mutex_type& __m, defer_lock_t) noexcept
482       : _M_device(&__m), _M_owns(false)
483       { }
484
485       unique_lock(mutex_type& __m, try_to_lock_t)
486       : _M_device(&__m), _M_owns(_M_device->try_lock())
487       { }
488
489       unique_lock(mutex_type& __m, adopt_lock_t)
490       : _M_device(&__m), _M_owns(true)
491       {
492         // XXX calling thread owns mutex
493       }
494
495       template<typename _Clock, typename _Duration>
496         unique_lock(mutex_type& __m,
497                     const chrono::time_point<_Clock, _Duration>& __atime)
498         : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime))
499         { }
500
501       template<typename _Rep, typename _Period>
502         unique_lock(mutex_type& __m,
503                     const chrono::duration<_Rep, _Period>& __rtime)
504         : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime))
505         { }
506
507       ~unique_lock()
508       {
509         if (_M_owns)
510           unlock();
511       }
512
513       unique_lock(const unique_lock&) = delete;
514       unique_lock& operator=(const unique_lock&) = delete;
515
516       unique_lock(unique_lock&& __u) noexcept
517       : _M_device(__u._M_device), _M_owns(__u._M_owns)
518       {
519         __u._M_device = 0;
520         __u._M_owns = false;
521       }
522
523       unique_lock& operator=(unique_lock&& __u) noexcept
524       {
525         if(_M_owns)
526           unlock();
527
528         unique_lock(std::move(__u)).swap(*this);
529
530         __u._M_device = 0;
531         __u._M_owns = false;
532
533         return *this;
534       }
535
536       void
537       lock()
538       {
539         if (!_M_device)
540           __throw_system_error(int(errc::operation_not_permitted));
541         else if (_M_owns)
542           __throw_system_error(int(errc::resource_deadlock_would_occur));
543         else
544           {
545             _M_device->lock();
546             _M_owns = true;
547           }
548       }
549
550       bool
551       try_lock()
552       {
553         if (!_M_device)
554           __throw_system_error(int(errc::operation_not_permitted));
555         else if (_M_owns)
556           __throw_system_error(int(errc::resource_deadlock_would_occur));
557         else
558           {
559             _M_owns = _M_device->try_lock();
560             return _M_owns;
561           }
562       }
563
564       template<typename _Clock, typename _Duration>
565         bool
566         try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
567         {
568           if (!_M_device)
569             __throw_system_error(int(errc::operation_not_permitted));
570           else if (_M_owns)
571             __throw_system_error(int(errc::resource_deadlock_would_occur));
572           else
573             {
574               _M_owns = _M_device->try_lock_until(__atime);
575               return _M_owns;
576             }
577         }
578
579       template<typename _Rep, typename _Period>
580         bool
581         try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
582         {
583           if (!_M_device)
584             __throw_system_error(int(errc::operation_not_permitted));
585           else if (_M_owns)
586             __throw_system_error(int(errc::resource_deadlock_would_occur));
587           else
588             {
589               _M_owns = _M_device->try_lock_for(__rtime);
590               return _M_owns;
591             }
592          }
593
594       void
595       unlock()
596       {
597         if (!_M_owns)
598           __throw_system_error(int(errc::operation_not_permitted));
599         else if (_M_device)
600           {
601             _M_device->unlock();
602             _M_owns = false;
603           }
604       }
605
606       void
607       swap(unique_lock& __u) noexcept
608       {
609         std::swap(_M_device, __u._M_device);
610         std::swap(_M_owns, __u._M_owns);
611       }
612
613       mutex_type*
614       release() noexcept
615       {
616         mutex_type* __ret = _M_device;
617         _M_device = 0;
618         _M_owns = false;
619         return __ret;
620       }
621
622       bool
623       owns_lock() const noexcept
624       { return _M_owns; }
625
626       explicit operator bool() const noexcept
627       { return owns_lock(); }
628
629       mutex_type*
630       mutex() const noexcept
631       { return _M_device; }
632
633     private:
634       mutex_type*       _M_device;
635       bool              _M_owns; // XXX use atomic_bool
636     };
637
638   /// Partial specialization for unique_lock objects.
639   template<typename _Mutex>
640     inline void
641     swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept
642     { __x.swap(__y); }
643
644   template<int _Idx>
645     struct __unlock_impl
646     {
647       template<typename... _Lock>
648         static void
649         __do_unlock(tuple<_Lock&...>& __locks)
650         {
651           std::get<_Idx>(__locks).unlock();
652           __unlock_impl<_Idx - 1>::__do_unlock(__locks);
653         }
654     };
655
656   template<>
657     struct __unlock_impl<-1>
658     {
659       template<typename... _Lock>
660         static void
661         __do_unlock(tuple<_Lock&...>&)
662         { }
663     };
664
665   template<typename _Lock>
666     unique_lock<_Lock>
667     __try_to_lock(_Lock& __l)
668     { return unique_lock<_Lock>(__l, try_to_lock); }
669
670   template<int _Idx, bool _Continue = true>
671     struct __try_lock_impl
672     {
673       template<typename... _Lock>
674         static void
675         __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
676         {
677           __idx = _Idx;
678           auto __lock = __try_to_lock(std::get<_Idx>(__locks));
679           if (__lock.owns_lock())
680             {
681               __try_lock_impl<_Idx + 1, _Idx + 2 < sizeof...(_Lock)>::
682                 __do_try_lock(__locks, __idx);
683               if (__idx == -1)
684                 __lock.release();
685             }
686         }
687     };
688
689   template<int _Idx>
690     struct __try_lock_impl<_Idx, false>
691     {
692       template<typename... _Lock>
693         static void
694         __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
695         {
696           __idx = _Idx;
697           auto __lock = __try_to_lock(std::get<_Idx>(__locks));
698           if (__lock.owns_lock())
699             {
700               __idx = -1;
701               __lock.release();
702             }
703         }
704     };
705
706   /** @brief Generic try_lock.
707    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
708    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
709    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
710    *  @return Returns -1 if all try_lock() calls return true. Otherwise returns
711    *          a 0-based index corresponding to the argument that returned false.
712    *  @post Either all arguments are locked, or none will be.
713    *
714    *  Sequentially calls try_lock() on each argument.
715    */
716   template<typename _Lock1, typename _Lock2, typename... _Lock3>
717     int
718     try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
719     {
720       int __idx;
721       auto __locks = std::tie(__l1, __l2, __l3...);
722       __try
723       { __try_lock_impl<0>::__do_try_lock(__locks, __idx); }
724       __catch(...)
725       { }
726       return __idx;
727     }
728
729   /** @brief Generic lock.
730    *  @param __l1 Meets Mutex requirements (try_lock() may throw).
731    *  @param __l2 Meets Mutex requirements (try_lock() may throw).
732    *  @param __l3 Meets Mutex requirements (try_lock() may throw).
733    *  @throw An exception thrown by an argument's lock() or try_lock() member.
734    *  @post All arguments are locked.
735    *
736    *  All arguments are locked via a sequence of calls to lock(), try_lock()
737    *  and unlock().  If the call exits via an exception any locks that were
738    *  obtained will be released.
739    */
740   template<typename _L1, typename _L2, typename ..._L3>
741     void
742     lock(_L1& __l1, _L2& __l2, _L3&... __l3)
743     {
744       while (true)
745         {
746           unique_lock<_L1> __first(__l1);
747           int __idx;
748           auto __locks = std::tie(__l2, __l3...);
749           __try_lock_impl<0, sizeof...(_L3)>::__do_try_lock(__locks, __idx);
750           if (__idx == -1)
751             {
752               __first.release();
753               return;
754             }
755         }
756     }
757
758   /// once_flag
759   struct once_flag
760   {
761   private:
762     typedef __gthread_once_t __native_type;
763     __native_type  _M_once;
764
765   public:
766     /// Constructor
767     constexpr once_flag() noexcept : _M_once(__GTHREAD_ONCE_INIT) { }
768
769     /// Deleted copy constructor
770     once_flag(const once_flag&) = delete;
771     /// Deleted assignment operator
772     once_flag& operator=(const once_flag&) = delete;
773
774     template<typename _Callable, typename... _Args>
775       friend void
776       call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
777   };
778
779 #ifdef _GLIBCXX_HAVE_TLS
780   extern __thread void* __once_callable;
781   extern __thread void (*__once_call)();
782
783   template<typename _Callable>
784     inline void
785     __once_call_impl()
786     {
787       (*(_Callable*)__once_callable)();
788     }
789 #else
790   extern function<void()> __once_functor;
791
792   extern void
793   __set_once_functor_lock_ptr(unique_lock<mutex>*);
794
795   extern mutex&
796   __get_once_mutex();
797 #endif
798
799   extern "C" void __once_proxy();
800
801   /// call_once
802   template<typename _Callable, typename... _Args>
803     void
804     call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
805     {
806 #ifdef _GLIBCXX_HAVE_TLS
807       auto __bound_functor = std::__bind_simple(std::forward<_Callable>(__f),
808           std::forward<_Args>(__args)...);
809       __once_callable = &__bound_functor;
810       __once_call = &__once_call_impl<decltype(__bound_functor)>;
811 #else
812       unique_lock<mutex> __functor_lock(__get_once_mutex());
813       __once_functor = std::__bind_simple(std::forward<_Callable>(__f),
814           std::forward<_Args>(__args)...);
815       __set_once_functor_lock_ptr(&__functor_lock);
816 #endif
817
818       int __e = __gthread_once(&(__once._M_once), &__once_proxy);
819
820 #ifndef _GLIBCXX_HAVE_TLS
821       if (__functor_lock)
822         __set_once_functor_lock_ptr(0);
823 #endif
824
825       if (__e)
826         __throw_system_error(__e);
827     }
828
829   // @} group mutexes
830 _GLIBCXX_END_NAMESPACE_VERSION
831 } // namespace
832
833 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
834
835 #endif // __GXX_EXPERIMENTAL_CXX0X__
836
837 #endif // _GLIBCXX_MUTEX