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