]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/std/mutex
Split <functional> into smaller pieces
[thirdparty/gcc.git] / libstdc++-v3 / include / std / mutex
CommitLineData
68a97d24
BK
1// <mutex> -*- C++ -*-
2
818ab71a 3// Copyright (C) 2003-2016 Free Software Foundation, Inc.
68a97d24
BK
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
748086b7 8// Free Software Foundation; either version 3, or (at your option)
68a97d24
BK
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
748086b7
JJ
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.
68a97d24 19
748086b7
JJ
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/>.
68a97d24 24
f910786b 25/** @file include/mutex
68a97d24
BK
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
734f5023 34#if __cplusplus < 201103L
ab65a4c7 35# include <bits/c++0x_warning.h>
57317d2a 36#else
68a97d24 37
57cb79ef 38#include <tuple>
7b800287
CF
39#include <chrono>
40#include <exception>
41#include <type_traits>
7b800287 42#include <system_error>
0c3e5dd1 43#include <bits/std_mutex.h>
f16081c2
JW
44#if ! _GTHREAD_USE_MUTEX_TIMEDLOCK
45# include <condition_variable>
46# include <thread>
47#endif
d67dd0be 48#ifndef _GLIBCXX_HAVE_TLS
c05986b9 49# include <bits/std_function.h>
d67dd0be 50#endif
7b800287 51
3442f18d 52#ifdef _GLIBCXX_USE_C99_STDINT_TR1
68a97d24 53
12ffa228
BK
54namespace std _GLIBCXX_VISIBILITY(default)
55{
56_GLIBCXX_BEGIN_NAMESPACE_VERSION
53dc5044 57
f16081c2
JW
58 /**
59 * @ingroup mutexes
60 * @{
61 */
b81e920e 62
f16081c2 63#ifdef _GLIBCXX_HAS_GTHREADS
b81e920e 64
d872e4aa 65 // Common base class for std::recursive_mutex and std::recursive_timed_mutex
b81e920e
JW
66 class __recursive_mutex_base
67 {
68 protected:
69 typedef __gthread_recursive_mutex_t __native_type;
70
71 __recursive_mutex_base(const __recursive_mutex_base&) = delete;
72 __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
73
74#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
75 __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
76
77 __recursive_mutex_base() = default;
78#else
79 __native_type _M_mutex;
80
81 __recursive_mutex_base()
82 {
83 // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
84 __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
85 }
86
87 ~__recursive_mutex_base()
1504e3e1 88 { __gthread_recursive_mutex_destroy(&_M_mutex); }
b81e920e
JW
89#endif
90 };
91
6b4f8906 92 /// The standard recursive mutex type.
b81e920e 93 class recursive_mutex : private __recursive_mutex_base
68a97d24
BK
94 {
95 public:
f7459b6c 96 typedef __native_type* native_handle_type;
68a97d24 97
b81e920e
JW
98 recursive_mutex() = default;
99 ~recursive_mutex() = default;
9916a9e4 100
7b800287
CF
101 recursive_mutex(const recursive_mutex&) = delete;
102 recursive_mutex& operator=(const recursive_mutex&) = delete;
103
4db6bc0f 104 void
68a97d24 105 lock()
4db6bc0f 106 {
68a97d24
BK
107 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
108
109 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
d3098c94
CF
110 if (__e)
111 __throw_system_error(__e);
68a97d24 112 }
4db6bc0f
BK
113
114 bool
7f0d79d5 115 try_lock() noexcept
68a97d24 116 {
22ac021b 117 // XXX EINVAL, EAGAIN, EBUSY
7b800287 118 return !__gthread_recursive_mutex_trylock(&_M_mutex);
68a97d24
BK
119 }
120
4db6bc0f 121 void
68a97d24 122 unlock()
4db6bc0f 123 {
22ac021b 124 // XXX EINVAL, EAGAIN, EBUSY
7b800287 125 __gthread_recursive_mutex_unlock(&_M_mutex);
68a97d24
BK
126 }
127
4db6bc0f 128 native_handle_type
2c15eace 129 native_handle() noexcept
7b800287 130 { return &_M_mutex; }
68a97d24
BK
131 };
132
3b2eeb43 133#if _GTHREAD_USE_MUTEX_TIMEDLOCK
25e00ab6
JW
134 template<typename _Derived>
135 class __timed_mutex_impl
136 {
137 protected:
25e00ab6 138 typedef chrono::high_resolution_clock __clock_t;
f7459b6c 139
25e00ab6
JW
140 template<typename _Rep, typename _Period>
141 bool
142 _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
143 {
61622399
JW
144 using chrono::steady_clock;
145 auto __rt = chrono::duration_cast<steady_clock::duration>(__rtime);
146 if (ratio_greater<steady_clock::period, _Period>())
25e00ab6 147 ++__rt;
61622399 148 return _M_try_lock_until(steady_clock::now() + __rt);
25e00ab6
JW
149 }
150
151 template<typename _Duration>
152 bool
153 _M_try_lock_until(const chrono::time_point<__clock_t,
154 _Duration>& __atime)
155 {
61622399
JW
156 auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
157 auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
25e00ab6
JW
158
159 __gthread_time_t __ts = {
160 static_cast<std::time_t>(__s.time_since_epoch().count()),
161 static_cast<long>(__ns.count())
162 };
163
d8e19f31 164 return static_cast<_Derived*>(this)->_M_timedlock(__ts);
25e00ab6
JW
165 }
166
167 template<typename _Clock, typename _Duration>
168 bool
169 _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
61622399
JW
170 {
171 auto __rtime = __atime - _Clock::now();
172 return _M_try_lock_until(__clock_t::now() + __rtime);
173 }
25e00ab6
JW
174 };
175
6b4f8906 176 /// The standard timed mutex type.
25e00ab6
JW
177 class timed_mutex
178 : private __mutex_base, public __timed_mutex_impl<timed_mutex>
179 {
d3098c94 180 public:
f7459b6c 181 typedef __native_type* native_handle_type;
d3098c94 182
b81e920e
JW
183 timed_mutex() = default;
184 ~timed_mutex() = default;
9916a9e4 185
7b800287
CF
186 timed_mutex(const timed_mutex&) = delete;
187 timed_mutex& operator=(const timed_mutex&) = delete;
188
189 void
190 lock()
191 {
192 int __e = __gthread_mutex_lock(&_M_mutex);
193
194 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
195 if (__e)
196 __throw_system_error(__e);
197 }
198
199 bool
7f0d79d5 200 try_lock() noexcept
7b800287
CF
201 {
202 // XXX EINVAL, EAGAIN, EBUSY
203 return !__gthread_mutex_trylock(&_M_mutex);
204 }
d3098c94
CF
205
206 template <class _Rep, class _Period>
207 bool
7b800287 208 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
25e00ab6 209 { return _M_try_lock_for(__rtime); }
d3098c94
CF
210
211 template <class _Clock, class _Duration>
212 bool
7b800287 213 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
25e00ab6 214 { return _M_try_lock_until(__atime); }
7b800287
CF
215
216 void
217 unlock()
218 {
219 // XXX EINVAL, EAGAIN, EBUSY
220 __gthread_mutex_unlock(&_M_mutex);
221 }
d3098c94
CF
222
223 native_handle_type
2c15eace 224 native_handle() noexcept
7b800287 225 { return &_M_mutex; }
d8e19f31
SH
226
227 private:
228 friend class __timed_mutex_impl<timed_mutex>;
229
230 bool
231 _M_timedlock(const __gthread_time_t& __ts)
232 { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); }
d3098c94
CF
233 };
234
235 /// recursive_timed_mutex
25e00ab6
JW
236 class recursive_timed_mutex
237 : private __recursive_mutex_base,
238 public __timed_mutex_impl<recursive_timed_mutex>
d3098c94
CF
239 {
240 public:
f7459b6c 241 typedef __native_type* native_handle_type;
7b800287 242
b81e920e
JW
243 recursive_timed_mutex() = default;
244 ~recursive_timed_mutex() = default;
9916a9e4 245
7b800287
CF
246 recursive_timed_mutex(const recursive_timed_mutex&) = delete;
247 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
248
249 void
250 lock()
251 {
252 int __e = __gthread_recursive_mutex_lock(&_M_mutex);
253
254 // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
255 if (__e)
256 __throw_system_error(__e);
257 }
d3098c94 258
7b800287 259 bool
7f0d79d5 260 try_lock() noexcept
7b800287
CF
261 {
262 // XXX EINVAL, EAGAIN, EBUSY
263 return !__gthread_recursive_mutex_trylock(&_M_mutex);
264 }
d3098c94
CF
265
266 template <class _Rep, class _Period>
267 bool
7b800287 268 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
25e00ab6 269 { return _M_try_lock_for(__rtime); }
d3098c94
CF
270
271 template <class _Clock, class _Duration>
272 bool
7b800287 273 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
25e00ab6 274 { return _M_try_lock_until(__atime); }
7b800287
CF
275
276 void
277 unlock()
278 {
279 // XXX EINVAL, EAGAIN, EBUSY
280 __gthread_recursive_mutex_unlock(&_M_mutex);
281 }
d3098c94
CF
282
283 native_handle_type
2c15eace 284 native_handle() noexcept
7b800287 285 { return &_M_mutex; }
d8e19f31
SH
286
287 private:
288 friend class __timed_mutex_impl<recursive_timed_mutex>;
289
290 bool
291 _M_timedlock(const __gthread_time_t& __ts)
292 { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); }
d3098c94 293 };
68a97d24 294
f16081c2 295#else // !_GTHREAD_USE_MUTEX_TIMEDLOCK
68a97d24 296
f16081c2
JW
297 /// timed_mutex
298 class timed_mutex
299 {
300 mutex _M_mut;
301 condition_variable _M_cv;
302 bool _M_locked = false;
68a97d24 303
f16081c2 304 public:
68a97d24 305
f16081c2 306 timed_mutex() = default;
2f1e8e7c 307 ~timed_mutex() { __glibcxx_assert( !_M_locked ); }
7b800287 308
f16081c2
JW
309 timed_mutex(const timed_mutex&) = delete;
310 timed_mutex& operator=(const timed_mutex&) = delete;
68a97d24 311
f16081c2
JW
312 void
313 lock()
68a97d24 314 {
f16081c2
JW
315 unique_lock<mutex> __lk(_M_mut);
316 _M_cv.wait(__lk, [&]{ return !_M_locked; });
317 _M_locked = true;
318 }
f7459b6c 319
f16081c2
JW
320 bool
321 try_lock()
322 {
323 lock_guard<mutex> __lk(_M_mut);
324 if (_M_locked)
325 return false;
326 _M_locked = true;
327 return true;
328 }
68a97d24 329
f16081c2
JW
330 template<typename _Rep, typename _Period>
331 bool
332 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
4db6bc0f 333 {
f16081c2
JW
334 unique_lock<mutex> __lk(_M_mut);
335 if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; }))
336 return false;
337 _M_locked = true;
338 return true;
68a97d24 339 }
4db6bc0f 340
f16081c2
JW
341 template<typename _Clock, typename _Duration>
342 bool
343 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
68a97d24 344 {
f16081c2
JW
345 unique_lock<mutex> __lk(_M_mut);
346 if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; }))
347 return false;
348 _M_locked = true;
349 return true;
68a97d24
BK
350 }
351
f16081c2
JW
352 void
353 unlock()
354 {
355 lock_guard<mutex> __lk(_M_mut);
2f1e8e7c 356 __glibcxx_assert( _M_locked );
f16081c2
JW
357 _M_locked = false;
358 _M_cv.notify_one();
359 }
360 };
68a97d24 361
f16081c2
JW
362 /// recursive_timed_mutex
363 class recursive_timed_mutex
364 {
365 mutex _M_mut;
366 condition_variable _M_cv;
367 thread::id _M_owner;
368 unsigned _M_count = 0;
68a97d24 369
f16081c2
JW
370 // Predicate type that tests whether the current thread can lock a mutex.
371 struct _Can_lock
372 {
f16081c2
JW
373 // Returns true if the mutex is unlocked or is locked by _M_caller.
374 bool
375 operator()() const noexcept
376 { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; }
7b800287 377
f16081c2
JW
378 const recursive_timed_mutex* _M_mx;
379 thread::id _M_caller;
380 };
7b800287 381
f16081c2 382 public:
f7459b6c 383
f16081c2 384 recursive_timed_mutex() = default;
2f1e8e7c 385 ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); }
68a97d24 386
f16081c2
JW
387 recursive_timed_mutex(const recursive_timed_mutex&) = delete;
388 recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
f7459b6c 389
f16081c2
JW
390 void
391 lock()
392 {
c79c59f0
JW
393 auto __id = this_thread::get_id();
394 _Can_lock __can_lock{this, __id};
f16081c2
JW
395 unique_lock<mutex> __lk(_M_mut);
396 _M_cv.wait(__lk, __can_lock);
397 if (_M_count == -1u)
398 __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3
399 _M_owner = __id;
400 ++_M_count;
401 }
402
403 bool
404 try_lock()
405 {
c79c59f0
JW
406 auto __id = this_thread::get_id();
407 _Can_lock __can_lock{this, __id};
f16081c2
JW
408 lock_guard<mutex> __lk(_M_mut);
409 if (!__can_lock())
410 return false;
411 if (_M_count == -1u)
412 return false;
413 _M_owner = __id;
414 ++_M_count;
415 return true;
416 }
68a97d24 417
f16081c2
JW
418 template<typename _Rep, typename _Period>
419 bool
420 try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
4db6bc0f 421 {
c79c59f0
JW
422 auto __id = this_thread::get_id();
423 _Can_lock __can_lock{this, __id};
f16081c2 424 unique_lock<mutex> __lk(_M_mut);
c79c59f0 425 if (!_M_cv.wait_for(__lk, __rtime, __can_lock))
f16081c2
JW
426 return false;
427 if (_M_count == -1u)
428 return false;
429 _M_owner = __id;
430 ++_M_count;
431 return true;
68a97d24
BK
432 }
433
f16081c2 434 template<typename _Clock, typename _Duration>
4db6bc0f 435 bool
f16081c2 436 try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
4db6bc0f 437 {
c79c59f0
JW
438 auto __id = this_thread::get_id();
439 _Can_lock __can_lock{this, __id};
f16081c2 440 unique_lock<mutex> __lk(_M_mut);
c79c59f0 441 if (!_M_cv.wait_until(__lk, __atime, __can_lock))
f16081c2
JW
442 return false;
443 if (_M_count == -1u)
444 return false;
445 _M_owner = __id;
446 ++_M_count;
447 return true;
68a97d24
BK
448 }
449
f16081c2
JW
450 void
451 unlock()
452 {
453 lock_guard<mutex> __lk(_M_mut);
2f1e8e7c
JW
454 __glibcxx_assert( _M_owner == this_thread::get_id() );
455 __glibcxx_assert( _M_count > 0 );
f16081c2 456 if (--_M_count == 0)
f7459b6c 457 {
f16081c2
JW
458 _M_owner = {};
459 _M_cv.notify_one();
7b800287 460 }
f16081c2
JW
461 }
462 };
f7459b6c 463
f16081c2
JW
464#endif
465#endif // _GLIBCXX_HAS_GTHREADS
68a97d24 466
9b2b801a 467 template<typename _Lock>
b82f988e 468 inline unique_lock<_Lock>
9b2b801a 469 __try_to_lock(_Lock& __l)
b82f988e 470 { return unique_lock<_Lock>{__l, try_to_lock}; }
9b2b801a 471
57cb79ef
CF
472 template<int _Idx, bool _Continue = true>
473 struct __try_lock_impl
474 {
475 template<typename... _Lock>
9b2b801a
JW
476 static void
477 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
f7459b6c 478 {
9b2b801a 479 __idx = _Idx;
b82f988e 480 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
9b2b801a
JW
481 if (__lock.owns_lock())
482 {
b82f988e
JW
483 constexpr bool __cont = _Idx + 2 < sizeof...(_Lock);
484 using __try_locker = __try_lock_impl<_Idx + 1, __cont>;
485 __try_locker::__do_try_lock(__locks, __idx);
9b2b801a
JW
486 if (__idx == -1)
487 __lock.release();
488 }
57cb79ef
CF
489 }
490 };
f7459b6c 491
57cb79ef
CF
492 template<int _Idx>
493 struct __try_lock_impl<_Idx, false>
494 {
495 template<typename... _Lock>
9b2b801a
JW
496 static void
497 __do_try_lock(tuple<_Lock&...>& __locks, int& __idx)
f7459b6c 498 {
9b2b801a 499 __idx = _Idx;
b82f988e 500 auto __lock = std::__try_to_lock(std::get<_Idx>(__locks));
9b2b801a
JW
501 if (__lock.owns_lock())
502 {
503 __idx = -1;
504 __lock.release();
505 }
57cb79ef
CF
506 }
507 };
f7459b6c 508
57cb79ef
CF
509 /** @brief Generic try_lock.
510 * @param __l1 Meets Mutex requirements (try_lock() may throw).
511 * @param __l2 Meets Mutex requirements (try_lock() may throw).
512 * @param __l3 Meets Mutex requirements (try_lock() may throw).
f7459b6c 513 * @return Returns -1 if all try_lock() calls return true. Otherwise returns
57cb79ef
CF
514 * a 0-based index corresponding to the argument that returned false.
515 * @post Either all arguments are locked, or none will be.
516 *
517 * Sequentially calls try_lock() on each argument.
518 */
519 template<typename _Lock1, typename _Lock2, typename... _Lock3>
4db6bc0f 520 int
57cb79ef
CF
521 try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3)
522 {
9b2b801a
JW
523 int __idx;
524 auto __locks = std::tie(__l1, __l2, __l3...);
726d3136 525 __try_lock_impl<0>::__do_try_lock(__locks, __idx);
9b2b801a 526 return __idx;
57cb79ef 527 }
68a97d24 528
9b2b801a
JW
529 /** @brief Generic lock.
530 * @param __l1 Meets Mutex requirements (try_lock() may throw).
531 * @param __l2 Meets Mutex requirements (try_lock() may throw).
532 * @param __l3 Meets Mutex requirements (try_lock() may throw).
533 * @throw An exception thrown by an argument's lock() or try_lock() member.
534 * @post All arguments are locked.
535 *
536 * All arguments are locked via a sequence of calls to lock(), try_lock()
537 * and unlock(). If the call exits via an exception any locks that were
538 * obtained will be released.
539 */
b82f988e 540 template<typename _L1, typename _L2, typename... _L3>
4db6bc0f 541 void
9b2b801a
JW
542 lock(_L1& __l1, _L2& __l2, _L3&... __l3)
543 {
544 while (true)
545 {
b82f988e 546 using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>;
9b2b801a
JW
547 unique_lock<_L1> __first(__l1);
548 int __idx;
549 auto __locks = std::tie(__l2, __l3...);
b82f988e 550 __try_locker::__do_try_lock(__locks, __idx);
9b2b801a
JW
551 if (__idx == -1)
552 {
553 __first.release();
554 return;
555 }
556 }
557 }
68a97d24 558
3442f18d 559#ifdef _GLIBCXX_HAS_GTHREADS
68a97d24 560 /// once_flag
4db6bc0f 561 struct once_flag
68a97d24 562 {
f7459b6c 563 private:
68a97d24 564 typedef __gthread_once_t __native_type;
eed33268 565 __native_type _M_once = __GTHREAD_ONCE_INIT;
68a97d24 566
f7459b6c 567 public:
e06745c1 568 /// Constructor
eed33268 569 constexpr once_flag() noexcept = default;
f7459b6c 570
e06745c1 571 /// Deleted copy constructor
7b800287 572 once_flag(const once_flag&) = delete;
e06745c1 573 /// Deleted assignment operator
7b800287 574 once_flag& operator=(const once_flag&) = delete;
68a97d24 575
7b800287
CF
576 template<typename _Callable, typename... _Args>
577 friend void
1b3fad81 578 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args);
68a97d24
BK
579 };
580
7b800287
CF
581#ifdef _GLIBCXX_HAVE_TLS
582 extern __thread void* __once_callable;
583 extern __thread void (*__once_call)();
7b800287
CF
584#else
585 extern function<void()> __once_functor;
99827523 586
efdb7347
JW
587 extern void
588 __set_once_functor_lock_ptr(unique_lock<mutex>*);
589
590 extern mutex&
591 __get_once_mutex();
7b800287
CF
592#endif
593
ff02a38b 594 extern "C" void __once_proxy(void);
7b800287 595
5b9daa7e 596 /// call_once
68a97d24 597 template<typename _Callable, typename... _Args>
4db6bc0f 598 void
1b3fad81 599 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args)
68a97d24 600 {
164b41eb
JW
601 // _GLIBCXX_RESOLVE_LIB_DEFECTS
602 // 2442. call_once() shouldn't DECAY_COPY()
cfbdc34f 603 auto __callable = [&] {
164b41eb
JW
604 std::__invoke(std::forward<_Callable>(__f),
605 std::forward<_Args>(__args)...);
606 };
cfbdc34f
JW
607#ifdef _GLIBCXX_HAVE_TLS
608 __once_callable = std::__addressof(__callable);
609 __once_call = []{ (*(decltype(__callable)*)__once_callable)(); };
610#else
611 unique_lock<mutex> __functor_lock(__get_once_mutex());
612 __once_functor = __callable;
efdb7347 613 __set_once_functor_lock_ptr(&__functor_lock);
7b800287 614#endif
f7459b6c 615
bd24ec2d 616 int __e = __gthread_once(&__once._M_once, &__once_proxy);
7b800287 617
cca36d72
PC
618#ifndef _GLIBCXX_HAVE_TLS
619 if (__functor_lock)
efdb7347 620 __set_once_functor_lock_ptr(0);
cca36d72
PC
621#endif
622
4db6bc0f 623 if (__e)
68a97d24
BK
624 __throw_system_error(__e);
625 }
3442f18d 626#endif // _GLIBCXX_HAS_GTHREADS
5b9daa7e
BK
627
628 // @} group mutexes
12ffa228
BK
629_GLIBCXX_END_NAMESPACE_VERSION
630} // namespace
3442f18d 631#endif // _GLIBCXX_USE_C99_STDINT_TR1
7b800287 632
734f5023 633#endif // C++11
68a97d24 634
57317d2a 635#endif // _GLIBCXX_MUTEX