diff options
| author | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-09-03 17:46:09 +0000 |
|---|---|---|
| committer | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-09-03 17:46:09 +0000 |
| commit | 5cee57306a94bbf411aeeb3ff4ddf7ce93d234d6 (patch) | |
| tree | d4e66635e0cfe9caf75b3797c3a505af165f7817 /libstdc++-v3/include/std/mutex | |
| parent | bc0f586a7a98dd3160f3e6477a0de3da7baa715a (diff) | |
| download | ppe42-gcc-5cee57306a94bbf411aeeb3ff4ddf7ce93d234d6.tar.gz ppe42-gcc-5cee57306a94bbf411aeeb3ff4ddf7ce93d234d6.zip | |
2008-09-03 Chris Fairles <chris.fairles@gmail.com>
* include/std/condition_variable: Use new deleted ctors.
* include/std/mutex: Likewise plus implement timed_mutex,
recursive_timed_mutex and call_once.
* src/condition_variable.cc: Implement wait(). Use gthread types.
Remove _GTHREADS_HAS_COND checks in favor of global
_GLIBCXX_HAS_GTHREADS.
* src/mutex.cc (call_once): Implementation using TLS with mutex
fallback.
* config/abi/pre/gnu.ver: Add exported symbols.
* testsuite/lib/libstdc++.exp (check_v3_target_gthreads): New.
* testsuite/lib/dg-options.exp (dg-require-gthreads): Likewise.
* testsuite/30_threads/lock_guard/requirements/typedefs.cc: Use
dg-require-gthreads and dg-require-cstdint.
* testsuite/30_threads/lock_guard/requirements/
explicit_instantiation.cc: Likewise.
* testsuite/30_threads/mutex/dest/destructor_locked.cc: Likewise.
* testsuite/30_threads/mutex/native_handle/1.cc: Likewise.
* testsuite/30_threads/mutex/cons/1.cc: Likewise.
* testsuite/30_threads/mutex/requirements/typedefs.cc: Likewise.
* testsuite/30_threads/mutex/try_lock/1.cc: Likewise.
* testsuite/30_threads/mutex/try_lock/2.cc: Likewise.
* testsuite/30_threads/mutex/lock/1.cc: Likewise.
* testsuite/30_threads/mutex/unlock/1.cc: Likewise.
* testsuite/30_threads/recursive_mutex/dest/destructor_locked.cc:
Likewise.
* testsuite/30_threads/recursive_mutex/native_handle/1.cc: Likewise.
* testsuite/30_threads/recursive_mutex/cons/1.cc: Likewise.
* testsuite/30_threads/recursive_mutex/requirements/typedefs.cc:
Likewise.
* testsuite/30_threads/recursive_mutex/try_lock/1.cc: Likewise.
* testsuite/30_threads/recursive_mutex/try_lock/2.cc: Likewise.
* testsuite/30_threads/recursive_mutex/lock/1.cc: Likewise.
* testsuite/30_threads/recursive_mutex/unlock/1.cc: Likewise.
* testsuite/30_threads/unique_lock/requirements/
explicit_instantiation.cc: Likewise.
* testsuite/30_threads/unique_lock/requirements/typedefs.cc: Likewise.
* testsuite/30_threads/mutex/cons/assign_neg.cc: Also adjust dg-error
lines for deleted members.
* testsuite/30_threads/mutex/cons/copy_neg.cc: Likewise.
* testsuite/30_threads/recursive_mutex/cons/assign_neg.cc: Likewise.
* testsuite/30_threads/recursive_mutex/cons/copy_neg.cc: Likewise.
* testsuite/30_threads/call_once/once_flag.cc: New.
* testsuite/30_threads/call_once/call_once1.cc: Likewise.
* testsuite/30_threads/condition_variable/cons/1.cc: Likewise.
* testsuite/30_threads/condition_variable/cons/copy_neg.cc: Likewise
* testsuite/30_threads/condition_variable/cons/assign_neg.cc: Likewise.
* testsuite/30_threads/condition_variable_any/cons/1.cc: Likewise.
* testsuite/30_threads/condition_variable_any/cons/copy_neg.cc:
Likewise.
* testsuite/30_threads/condition_variable_any/cons/assign_neg.cc:
Likewise.
* testsuite/30_threads/timed_mutex/dest/destructor_locked.cc: Likewise.
* testsuite/30_threads/timed_mutex/native_handle/1.cc: Likewise.
* testsuite/30_threads/timed_mutex/try_lock_until/1.cc: Likewise.
* testsuite/30_threads/timed_mutex/try_lock_until/2.cc: Likewise.
* testsuite/30_threads/timed_mutex/cons/assign_neg.cc: Likewise.
* testsuite/30_threads/timed_mutex/cons/1.cc: Likewise.
* testsuite/30_threads/timed_mutex/cons/copy_neg.cc: Likewise.
* testsuite/30_threads/timed_mutex/requirements/typedefs.cc: Likewise.
* testsuite/30_threads/timed_mutex/try_lock/1.cc: Likewise.
* testsuite/30_threads/timed_mutex/try_lock/2.cc: Likewise.
* testsuite/30_threads/timed_mutex/lock/1.cc: Likewise.
* testsuite/30_threads/timed_mutex/unlock/1.cc: Likewise.
* testsuite/30_threads/timed_mutex/try_lock_for/1.cc: Likewise.
* testsuite/30_threads/timed_mutex/try_lock_for/2.cc: Likewise.
* testsuite/30_threads/timed_mutex/try_lock_for/3.cc: Likewise.
* testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc:
Likewise.
* testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc:
Likewise.
* testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc:
Likewise.
* testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc:
Likewise.
* testsuite/30_threads/recursive_timed_mutex/cons: Likewise.
* testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc:
Likewise.
* testsuite/30_threads/recursive_timed_mutex/cons/1.cc: Likewise.
* testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc: Likewise.
* testsuite/30_threads/recursive_timed_mutex/requirements/typedefs.cc:
Likewise.
* testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc: Likewise.
* testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc: Likewise.
* testsuite/30_threads/recursive_timed_mutex/lock/1.cc: Likewise.
* testsuite/30_threads/recursive_timed_mutex/lock/2.cc: Likewise.
* testsuite/30_threads/recursive_timed_mutex/unlock/1.cc: Likewise.
* testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc:
Likewise.
* testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc:
Likewise.
* testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc:
Likewise.
* testsuite/30_threads/unique_lock/modifiers/1.cc: Likewise.
* testsuite/30_threads/unique_lock/modifiers/2.cc: Likewise.
* testsuite/30_threads/unique_lock/cons/1.cc: Likewise.
* testsuite/30_threads/unique_lock/cons/2.cc: Likewise.
* testsuite/30_threads/unique_lock/cons/3.cc: Likewise.
* testsuite/30_threads/unique_lock/cons/4.cc: Likewise.
* testsuite/30_threads/unique_lock/cons/5.cc: Likewise.
* testsuite/30_threads/unique_lock/cons/6.cc: Likewise.
* testsuite/30_threads/unique_lock/locking/1.cc: Likewise.
* testsuite/30_threads/unique_lock/locking/2.cc: Likewise.
* testsuite/30_threads/unique_lock/locking/3.cc: Likewise.
* testsuite/30_threads/unique_lock/locking/4.cc: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139943 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3/include/std/mutex')
| -rw-r--r-- | libstdc++-v3/include/std/mutex | 442 |
1 files changed, 340 insertions, 102 deletions
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex index 779394a5891..5e6ba9c2715 100644 --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -41,39 +41,40 @@ # include <c++0x_warning.h> #else -#include <exception> #include <cstddef> +#include <chrono> +#include <exception> +#include <type_traits> +#include <functional> +#include <system_error> #include <bits/functexcept.h> #include <bits/gthr.h> +#include <bits/move.h> // for std::swap + +#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) namespace std { - namespace chrono - { - template<typename _Rep, typename _Period> - struct duration; - - template<typename _Clock, typename _Duration> - struct time_point; - } - /// mutex class mutex { public: - typedef __gthread_mutex_t native_handle_type; + typedef __gthread_mutex_t* native_handle_type; mutex() { // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) -#if defined __GTHREAD_MUTEX_INIT - native_handle_type __tmp = __GTHREAD_MUTEX_INIT; +#ifdef __GTHREAD_MUTEX_INIT + __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT; _M_mutex = __tmp; #else __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); #endif } + mutex(const mutex&) = delete; + mutex& operator=(const mutex&) = delete; + void lock() { @@ -100,31 +101,32 @@ namespace std native_handle_type native_handle() - { return _M_mutex; } + { return &_M_mutex; } private: - native_handle_type _M_mutex; - mutex(const mutex&); - mutex& operator=(const mutex&); + __gthread_mutex_t _M_mutex; }; /// recursive_mutex class recursive_mutex { public: - typedef __gthread_recursive_mutex_t native_handle_type; + typedef __gthread_recursive_mutex_t* native_handle_type; recursive_mutex() { // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) -#if defined __GTHREAD_RECURSIVE_MUTEX_INIT - native_handle_type __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT; +#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT + __gthread_recursive_mutex_t __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT; _M_mutex = __tmp; #else __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); #endif } + recursive_mutex(const recursive_mutex&) = delete; + recursive_mutex& operator=(const recursive_mutex&) = delete; + void lock() { @@ -139,85 +141,227 @@ namespace std try_lock() { // XXX EINVAL, EAGAIN, EBUSY - return !__gthread_recursive_mutex_trylock(&_M_mutex); + return !__gthread_recursive_mutex_trylock(&_M_mutex); } void unlock() { // XXX EINVAL, EAGAIN, EBUSY - __gthread_recursive_mutex_unlock(&_M_mutex); + __gthread_recursive_mutex_unlock(&_M_mutex); } native_handle_type native_handle() - { return _M_mutex; } + { return &_M_mutex; } private: - native_handle_type _M_mutex; - - recursive_mutex(const recursive_mutex&); - recursive_mutex& operator=(const recursive_mutex&); + __gthread_recursive_mutex_t _M_mutex; }; /// timed_mutex class timed_mutex - { + { public: - typedef __gthread_mutex_t native_handle_type; + typedef __gthread_mutex_t* native_handle_type; - void lock(); - bool try_lock(); + timed_mutex() + { +#ifdef __GTHREAD_MUTEX_INIT + __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT; + _M_mutex = __tmp; +#else + __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); +#endif + } + + timed_mutex(const timed_mutex&) = delete; + timed_mutex& operator=(const timed_mutex&) = delete; + + void + lock() + { + int __e = __gthread_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } + + bool + try_lock() + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_mutex_trylock(&_M_mutex); + } template <class _Rep, class _Period> bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rtime); + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { return __try_lock_for_impl(__rtime); } template <class _Clock, class _Duration> bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime); + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { + chrono::time_point<_Clock, chrono::seconds> __s = + chrono::time_point_cast<chrono::seconds>(__atime); + + chrono::nanoseconds __ns = + chrono::duration_cast<chrono::nanoseconds>(__atime - __s); + + __gthread_time_t __ts = { + static_cast<std::time_t>(__s.time_since_epoch().count()), + static_cast<long>(__ns.count()) + }; - void unlock(); + return !__gthread_mutex_timedlock(&_M_mutex, &__ts); + } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EBUSY + __gthread_mutex_unlock(&_M_mutex); + } native_handle_type native_handle() - { return _M_mutex; } + { return &_M_mutex; } private: - native_handle_type _M_mutex; + __gthread_mutex_t _M_mutex; + +#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC + typedef chrono::monotonic_clock __clock_t; +#else + typedef chrono::high_resolution_clock __clock_t; +#endif - timed_mutex(const timed_mutex&); - timed_mutex& operator=(const timed_mutex&); + template<typename _Rep, typename _Period> + typename enable_if< + ratio_less_equal<__clock_t::period, _Period>::value, bool>::type + __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime) + { + __clock_t::time_point __atime = __clock_t::now() + + chrono::duration_cast<__clock_t::duration>(__rtime); + + return try_lock_until(__atime); + } + + template <typename _Rep, typename _Period> + typename enable_if< + !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type + __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime) + { + __clock_t::time_point __atime = __clock_t::now() + + ++chrono::duration_cast<__clock_t::duration>(__rtime); + + return try_lock_until(__atime); + } }; /// recursive_timed_mutex class recursive_timed_mutex { public: - typedef __gthread_mutex_t native_handle_type; + typedef __gthread_recursive_mutex_t* native_handle_type; + + recursive_timed_mutex() + { + // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) +#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT + __gthread_recursive_mutex_t __tmp = __GTHREAD_RECURSIVE_MUTEX_INIT; + _M_mutex = __tmp; +#else + __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); +#endif + } + + recursive_timed_mutex(const recursive_timed_mutex&) = delete; + recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; + + void + lock() + { + int __e = __gthread_recursive_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } - void lock(); - bool try_lock(); + bool + try_lock() + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_recursive_mutex_trylock(&_M_mutex); + } template <class _Rep, class _Period> bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rtime); + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { return __try_lock_for_impl(__rtime); } template <class _Clock, class _Duration> bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime); + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { + chrono::time_point<_Clock, chrono::seconds> __s = + chrono::time_point_cast<chrono::seconds>(__atime); + + chrono::nanoseconds __ns = + chrono::duration_cast<chrono::nanoseconds>(__atime - __s); - void unlock(); + __gthread_time_t __ts = { + static_cast<std::time_t>(__s.time_since_epoch().count()), + static_cast<long>(__ns.count()) + }; + + return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); + } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EBUSY + __gthread_recursive_mutex_unlock(&_M_mutex); + } native_handle_type native_handle() - { return _M_mutex; } - + { return &_M_mutex; } + private: - native_handle_type _M_mutex; + __gthread_recursive_mutex_t _M_mutex; - recursive_timed_mutex(const recursive_timed_mutex&); - recursive_timed_mutex& operator=(const recursive_timed_mutex&); +#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC + typedef chrono::monotonic_clock __clock_t; +#else + typedef chrono::high_resolution_clock __clock_t; +#endif + + template<typename _Rep, typename _Period> + typename enable_if< + ratio_less_equal<__clock_t::period, _Period>::value, bool>::type + __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime) + { + __clock_t::time_point __atime = __clock_t::now() + + chrono::duration_cast<__clock_t::duration>(__rtime); + + return try_lock_until(__atime); + } + + template <typename _Rep, typename _Period> + typename enable_if< + !ratio_less_equal<__clock_t::period, _Period>::value, bool>::type + __try_lock_for_impl(const chrono::duration<_Rep, _Period>& __rtime) + { + __clock_t::time_point __atime = __clock_t::now() + + ++chrono::duration_cast<__clock_t::duration>(__rtime); + + return try_lock_until(__atime); + } }; /// Do not acquire ownership of the mutex. @@ -260,10 +404,11 @@ namespace std ~lock_guard() { _M_device.unlock(); } + lock_guard(const lock_guard&) = delete; + lock_guard& operator=(const lock_guard&) = delete; + private: mutex_type& _M_device; - lock_guard(lock_guard const&); - lock_guard& operator=(lock_guard const&); }; /// unique_lock @@ -272,13 +417,13 @@ namespace std { public: typedef _Mutex mutex_type; - + unique_lock() - : _M_device(NULL), _M_owns(false) + : _M_device(0), _M_owns(false) { } explicit unique_lock(mutex_type& __m) - : _M_device(&__m) + : _M_device(&__m), _M_owns(false) { lock(); _M_owns = true; @@ -300,11 +445,15 @@ namespace std template<typename _Clock, typename _Duration> unique_lock(mutex_type& __m, - const chrono::time_point<_Clock, _Duration>& __atime); + const chrono::time_point<_Clock, _Duration>& __atime) + : _M_device(&__m), _M_owns(_M_device->try_lock_until(__atime)) + { } template<typename _Rep, typename _Period> unique_lock(mutex_type& __m, - const chrono::duration<_Rep, _Period>& __rtime); + const chrono::duration<_Rep, _Period>& __rtime) + : _M_device(&__m), _M_owns(_M_device->try_lock_for(__rtime)) + { } ~unique_lock() { @@ -312,55 +461,111 @@ namespace std unlock(); } - unique_lock(unique_lock&&); + unique_lock(const unique_lock&) = delete; + unique_lock& operator=(const unique_lock&) = delete; + + unique_lock(unique_lock&& __u) + : _M_device(__u._M_device), _M_owns(__u._M_owns) + { + __u._M_device = 0; + __u._M_owns = false; + } + + unique_lock& operator=(unique_lock&& __u) + { + if(_M_owns) + unlock(); + + unique_lock(std::move(__u)).swap(*this); - unique_lock& operator=(unique_lock&&); + __u._M_device = 0; + __u._M_owns = false; + + return *this; + } void lock() { - if (_M_device && !_M_owns) - _M_device->lock(); + if (!_M_device) + __throw_system_error(posix_error::operation_not_permitted); + else if (_M_owns) + __throw_system_error(posix_error::resource_deadlock_would_occur); else - throw lock_error(); + { + _M_device->lock(); + _M_owns = true; + } } bool try_lock() { - bool __ret = false; - if (_M_device && !_M_owns) - __ret = _M_device->try_lock(); - else - throw lock_error(); - return __ret; + if (!_M_device) + __throw_system_error(posix_error::operation_not_permitted); + else if (_M_owns) + __throw_system_error(posix_error::resource_deadlock_would_occur); + else + { + _M_owns = _M_device->try_lock(); + return _M_owns; + } } + template<typename _Clock, typename _Duration> + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { + if (!_M_device) + __throw_system_error(posix_error::operation_not_permitted); + else if (_M_owns) + __throw_system_error(posix_error::resource_deadlock_would_occur); + else + { + _M_owns = _M_device->try_lock_until(__atime); + return _M_owns; + } + } + + template<typename _Rep, typename _Period> + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + if (!_M_device) + __throw_system_error(posix_error::operation_not_permitted); + else if (_M_owns) + __throw_system_error(posix_error::resource_deadlock_would_occur); + else + { + _M_owns = _M_device->try_lock_for(__rtime); + return _M_owns; + } + } + void unlock() { - if (_M_device && _M_owns) - _M_device->unlock(); - else - throw lock_error(); + if (!_M_owns) + __throw_system_error(posix_error::operation_not_permitted); + else if (_M_device) + { + _M_device->unlock(); + _M_owns = false; + } } - - template<typename _Rep, typename _Period> - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rtime); - - template<typename _Clock, typename _Duration> - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime); - + void - swap(unique_lock&& __u); + swap(unique_lock&& __u) + { + std::swap(_M_device, __u._M_device); + std::swap(_M_owns, __u._M_owns); + } mutex_type* release() { mutex_type* __ret = _M_device; - _M_device = NULL; + _M_device = 0; _M_owns = false; return __ret; } @@ -369,7 +574,7 @@ namespace std owns_lock() const { return _M_owns; } - operator bool () const + /* explicit */ operator bool () const { return owns_lock(); } mutex_type* @@ -377,28 +582,28 @@ namespace std { return _M_device; } private: - unique_lock(unique_lock const&); - unique_lock& operator=(unique_lock const&); - mutex_type* _M_device; bool _M_owns; // XXX use atomic_bool }; template<typename _Mutex> - void - swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y); + inline void + swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) + { __x.swap(__y); } template<typename _Mutex> - void - swap(unique_lock<_Mutex>&& __x, unique_lock<_Mutex>& __y); + inline void + swap(unique_lock<_Mutex>&& __x, unique_lock<_Mutex>& __y) + { __x.swap(__y); } template<typename _Mutex> - void - swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>&& __y); + inline void + swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>&& __y) + { __x.swap(__y); } template<typename _L1, typename _L2, typename ..._L3> int - try_lock(_L1&, _L2&, _L3&...); + try_lock(_L1& __l1, _L2& __l2, _L3&... __l3); template<typename _L1, typename _L2, typename ..._L3> void @@ -410,30 +615,63 @@ namespace std typedef __gthread_once_t __native_type; once_flag() - { - __native_type __tmp = __GTHREAD_ONCE_INIT; - _M_once = __tmp; - } + : _M_once(__GTHREAD_ONCE_INIT) + { } + + once_flag(const once_flag&) = delete; + once_flag& operator=(const once_flag&) = delete; - __native_type& - _M_get() { return _M_once; } + template<typename _Callable, typename... _Args> + friend void + call_once(once_flag& __once, _Callable __f, _Args&&... __args); private: __native_type _M_once; - once_flag(const once_flag&); - once_flag& operator=(const once_flag&); }; +#ifdef _GLIBCXX_HAVE_TLS + extern __thread void* __once_callable; + extern __thread void (*__once_call)(); + + template<typename _Callable> + void __once_call_impl() + { + (*(_Callable*)__once_callable)(); + } +#else + extern function<void()> __once_functor; + extern unique_lock<mutex> __once_functor_lock; +#endif + + extern "C" void __once_proxy(); + template<typename _Callable, typename... _Args> void call_once(once_flag& __once, _Callable __f, _Args&&... __args) { - int __e = __gthread_once(&(__once._M_get()), __f(__args...)); +#ifdef _GLIBCXX_HAVE_TLS + auto __bound_functor = bind(__f, __args...); + __once_callable = &__bound_functor; + __once_call = &__once_call_impl<decltype(__bound_functor)>; +#else + __once_functor_lock.lock(); + __once_functor = bind(__f, __args...); +#endif + + int __e = __gthread_once(&(__once._M_once), &__once_proxy); + +#ifndef _GLIBCXX_HAVE_TLS + if (__once_functor_lock) + __once_functor_lock.unlock(); +#endif + if (__e) __throw_system_error(__e); } } +#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 + #endif // __GXX_EXPERIMENTAL_CXX0X__ #endif // _GLIBCXX_MUTEX |

