summaryrefslogtreecommitdiffstats
path: root/libstdc++-v3/include/std/mutex
diff options
context:
space:
mode:
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2008-09-03 17:46:09 +0000
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>2008-09-03 17:46:09 +0000
commit5cee57306a94bbf411aeeb3ff4ddf7ce93d234d6 (patch)
treed4e66635e0cfe9caf75b3797c3a505af165f7817 /libstdc++-v3/include/std/mutex
parentbc0f586a7a98dd3160f3e6477a0de3da7baa715a (diff)
downloadppe42-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/mutex442
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
OpenPOWER on IntegriCloud