Commit b81e920e by Jonathan Wakely Committed by Jonathan Wakely

re PR libstdc++/49894 ([C++0x] Uniform initialization in constructor)

	PR libstdc++/49894
	* include/std/mutex (__mutex_base,__recursive_mutex_base): Define new
	base classes to manage construction/destruction of native mutexes,
	using NSDMI when INIT macros are defined.
	(mutex,recursive_mutex,timed_mutex,recursive_timed_mutex): Derive from
	new base classes.
	* include/std/condition_variable (condition_variable): Use NSDMI when
	INIT macro is defined. Use noexcept.
	* src/condition_variable.cc (condition_variable): Explicitly-default
	constructor/destructor when using NSDMI. Use noexcept.
	(condition_variable_any): Likewise.

From-SVN: r180411
parent cca3f03d
2011-10-25 Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/49894
* include/std/mutex (__mutex_base,__recursive_mutex_base): Define new
base classes to manage construction/destruction of native mutexes,
using NSDMI when INIT macros are defined.
(mutex,recursive_mutex,timed_mutex,recursive_timed_mutex): Derive from
new base classes.
* include/std/condition_variable (condition_variable): Use NSDMI when
INIT macro is defined. Use noexcept.
* src/condition_variable.cc (condition_variable): Explicitly-default
constructor/destructor when using NSDMI. Use noexcept.
(condition_variable_any): Likewise.
2011-10-24 Jonathan Wakely <jwakely.gcc@gmail.com> 2011-10-24 Jonathan Wakely <jwakely.gcc@gmail.com>
* testsuite/30_threads/async/49668.cc: Add missing dg-require. * testsuite/30_threads/async/49668.cc: Add missing dg-require.
......
...@@ -60,22 +60,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -60,22 +60,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ {
typedef chrono::system_clock __clock_t; typedef chrono::system_clock __clock_t;
typedef __gthread_cond_t __native_type; typedef __gthread_cond_t __native_type;
#ifdef __GTHREAD_COND_INIT
__native_type _M_cond = __GTHREAD_COND_INIT;
#else
__native_type _M_cond; __native_type _M_cond;
#endif
public: public:
typedef __native_type* native_handle_type; typedef __native_type* native_handle_type;
condition_variable() throw (); condition_variable() noexcept;
~condition_variable() throw (); ~condition_variable() noexcept;
condition_variable(const condition_variable&) = delete; condition_variable(const condition_variable&) = delete;
condition_variable& operator=(const condition_variable&) = delete; condition_variable& operator=(const condition_variable&) = delete;
void void
notify_one(); notify_one() noexcept;
void void
notify_all(); notify_all() noexcept;
void void
wait(unique_lock<mutex>& __lock); wait(unique_lock<mutex>& __lock);
...@@ -174,21 +179,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -174,21 +179,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public: public:
typedef condition_variable::native_handle_type native_handle_type; typedef condition_variable::native_handle_type native_handle_type;
condition_variable_any() throw (); condition_variable_any() noexcept;
~condition_variable_any() throw (); ~condition_variable_any() noexcept;
condition_variable_any(const condition_variable_any&) = delete; condition_variable_any(const condition_variable_any&) = delete;
condition_variable_any& operator=(const condition_variable_any&) = delete; condition_variable_any& operator=(const condition_variable_any&) = delete;
void void
notify_one() notify_one() noexcept
{ {
lock_guard<mutex> __lock(_M_mutex); lock_guard<mutex> __lock(_M_mutex);
_M_cond.notify_one(); _M_cond.notify_one();
} }
void void
notify_all() notify_all() noexcept
{ {
lock_guard<mutex> __lock(_M_mutex); lock_guard<mutex> __lock(_M_mutex);
_M_cond.notify_all(); _M_cond.notify_all();
......
...@@ -52,6 +52,94 @@ namespace std _GLIBCXX_VISIBILITY(default) ...@@ -52,6 +52,94 @@ namespace std _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Common base class for std::mutex and std::timed_mutex
class __mutex_base
{
protected:
typedef __gthread_mutex_t __native_type;
#ifdef __GTHREAD_MUTEX_INIT
__native_type _M_mutex = __GTHREAD_MUTEX_INIT;
constexpr __mutex_base() noexcept = default;
#else
__native_type _M_mutex;
__mutex_base() noexcept
{
// XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
__GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
}
~__mutex_base() { __gthread_mutex_destroy(&_M_mutex); }
#endif
__mutex_base(const __mutex_base&) = delete;
__mutex_base& operator=(const __mutex_base&) = delete;
};
// Common base class for std::recursive_mutex and std::timed_recursive_mutex
class __recursive_mutex_base
{
protected:
typedef __gthread_recursive_mutex_t __native_type;
__recursive_mutex_base(const __recursive_mutex_base&) = delete;
__recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
__native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
__recursive_mutex_base() = default;
#else
__native_type _M_mutex;
__recursive_mutex_base()
{
// XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
}
~__recursive_mutex_base()
{ _S_destroy(&_M_mutex); }
private:
// FIXME: gthreads doesn't define __gthread_recursive_mutex_destroy
// so we need to obtain a __gthread_mutex_t to destroy
// matches when there's only one mutex type
template<typename _Rm>
static
typename enable_if<is_same<_Rm, __gthread_mutex_t>::value, void>::type
_S_destroy(_Rm* __mx)
{ __gthread_mutex_destroy(__mx); }
// matches a recursive mutex with a member 'actual'
template<typename _Rm>
static typename enable_if<sizeof(&_Rm::actual), void>::type
_S_destroy(_Rm* __mx)
{ __gthread_mutex_destroy(&__mx->actual); }
// matches a gthr-win32.h recursive mutex
template<typename _Rm>
static typename enable_if<sizeof(&_Rm::sema), void>::type
_S_destroy(_Rm* __mx)
{
__gthread_mutex_t __tmp;
_S_destroy_win32(&__tmp, __mx);
}
template<typename _Mx, typename _Rm>
static void
_S_destroy_win32(_Mx* __mx, _Rm const* __rmx)
{
__mx->counter = __rmx->counter;
__mx->sema = __rmx->sema;
__gthread_mutex_destroy(__mx);
}
#endif
};
/** /**
* @defgroup mutexes Mutexes * @defgroup mutexes Mutexes
* @ingroup concurrency * @ingroup concurrency
...@@ -61,25 +149,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -61,25 +149,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/ */
/// mutex /// mutex
class mutex class mutex : private __mutex_base
{ {
typedef __gthread_mutex_t __native_type;
__native_type _M_mutex;
public: public:
typedef __native_type* native_handle_type; typedef __native_type* native_handle_type;
#ifdef __GTHREAD_MUTEX_INIT #ifdef __GTHREAD_MUTEX_INIT
constexpr mutex() noexcept : _M_mutex(__GTHREAD_MUTEX_INIT) { } constexpr
#else
mutex() noexcept
{
// XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
__GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
}
~mutex() { __gthread_mutex_destroy(&_M_mutex); }
#endif #endif
mutex() noexcept = default;
~mutex() = default;
mutex(const mutex&) = delete; mutex(const mutex&) = delete;
mutex& operator=(const mutex&) = delete; mutex& operator=(const mutex&) = delete;
...@@ -113,66 +192,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -113,66 +192,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return &_M_mutex; } { return &_M_mutex; }
}; };
#ifndef __GTHREAD_RECURSIVE_MUTEX_INIT
// FIXME: gthreads doesn't define __gthread_recursive_mutex_destroy
// so we need to obtain a __gthread_mutex_t to destroy
class __destroy_recursive_mutex
{
template<typename _Mx, typename _Rm>
static void
_S_destroy_win32(_Mx* __mx, _Rm const* __rmx)
{
__mx->counter = __rmx->counter;
__mx->sema = __rmx->sema;
__gthread_mutex_destroy(__mx);
}
public:
// matches a gthr-win32.h recursive mutex
template<typename _Rm>
static typename enable_if<sizeof(&_Rm::sema), void>::type
_S_destroy(_Rm* __mx)
{
__gthread_mutex_t __tmp;
_S_destroy_win32(&__tmp, __mx);
}
// matches a recursive mutex with a member 'actual'
template<typename _Rm>
static typename enable_if<sizeof(&_Rm::actual), void>::type
_S_destroy(_Rm* __mx)
{ __gthread_mutex_destroy(&__mx->actual); }
// matches when there's only one mutex type
template<typename _Rm>
static
typename enable_if<is_same<_Rm, __gthread_mutex_t>::value, void>::type
_S_destroy(_Rm* __mx)
{ __gthread_mutex_destroy(__mx); }
};
#endif
/// recursive_mutex /// recursive_mutex
class recursive_mutex class recursive_mutex : private __recursive_mutex_base
{ {
typedef __gthread_recursive_mutex_t __native_type;
__native_type _M_mutex;
public: public:
typedef __native_type* native_handle_type; typedef __native_type* native_handle_type;
#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT recursive_mutex() = default;
recursive_mutex() : _M_mutex(__GTHREAD_RECURSIVE_MUTEX_INIT) { } ~recursive_mutex() = default;
#else
recursive_mutex()
{
// XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
}
~recursive_mutex()
{ __destroy_recursive_mutex::_S_destroy(&_M_mutex); }
#endif
recursive_mutex(const recursive_mutex&) = delete; recursive_mutex(const recursive_mutex&) = delete;
recursive_mutex& operator=(const recursive_mutex&) = delete; recursive_mutex& operator=(const recursive_mutex&) = delete;
...@@ -208,31 +235,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -208,31 +235,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if _GTHREAD_USE_MUTEX_TIMEDLOCK #if _GTHREAD_USE_MUTEX_TIMEDLOCK
/// timed_mutex /// timed_mutex
class timed_mutex class timed_mutex : private __mutex_base
{ {
typedef __gthread_mutex_t __native_type;
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
typedef chrono::steady_clock __clock_t; typedef chrono::steady_clock __clock_t;
#else #else
typedef chrono::high_resolution_clock __clock_t; typedef chrono::high_resolution_clock __clock_t;
#endif #endif
__native_type _M_mutex;
public: public:
typedef __native_type* native_handle_type; typedef __native_type* native_handle_type;
#ifdef __GTHREAD_MUTEX_INIT timed_mutex() = default;
timed_mutex() : _M_mutex(__GTHREAD_MUTEX_INIT) { } ~timed_mutex() = default;
#else
timed_mutex()
{
__GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
}
~timed_mutex() { __gthread_mutex_destroy(&_M_mutex); }
#endif
timed_mutex(const timed_mutex&) = delete; timed_mutex(const timed_mutex&) = delete;
timed_mutex& operator=(const timed_mutex&) = delete; timed_mutex& operator=(const timed_mutex&) = delete;
...@@ -313,33 +328,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -313,33 +328,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}; };
/// recursive_timed_mutex /// recursive_timed_mutex
class recursive_timed_mutex class recursive_timed_mutex : private __recursive_mutex_base
{ {
typedef __gthread_recursive_mutex_t __native_type;
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
typedef chrono::steady_clock __clock_t; typedef chrono::steady_clock __clock_t;
#else #else
typedef chrono::high_resolution_clock __clock_t; typedef chrono::high_resolution_clock __clock_t;
#endif #endif
__native_type _M_mutex;
public: public:
typedef __native_type* native_handle_type; typedef __native_type* native_handle_type;
#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT recursive_timed_mutex() = default;
recursive_timed_mutex() : _M_mutex(__GTHREAD_RECURSIVE_MUTEX_INIT) { } ~recursive_timed_mutex() = default;
#else
recursive_timed_mutex()
{
// XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
}
~recursive_timed_mutex()
{ __destroy_recursive_mutex::_S_destroy(&_M_mutex); }
#endif
recursive_timed_mutex(const recursive_timed_mutex&) = delete; recursive_timed_mutex(const recursive_timed_mutex&) = delete;
recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
......
...@@ -30,25 +30,25 @@ namespace std _GLIBCXX_VISIBILITY(default) ...@@ -30,25 +30,25 @@ namespace std _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
condition_variable::condition_variable() throw ()
{
#ifdef __GTHREAD_COND_INIT #ifdef __GTHREAD_COND_INIT
__native_type __tmp = __GTHREAD_COND_INIT; condition_variable::condition_variable() = default;
_M_cond = __tmp; condition_variable::~condition_variable() = default;
#else #else
condition_variable::condition_variable() noexcept
{
int __e = __gthread_cond_init(&_M_cond, 0); int __e = __gthread_cond_init(&_M_cond, 0);
if (__e) if (__e)
__throw_system_error(__e); __throw_system_error(__e);
#endif
} }
condition_variable::~condition_variable() throw () condition_variable::~condition_variable() noexcept
{ {
// XXX no thread blocked // XXX no thread blocked
/* int __e = */ __gthread_cond_destroy(&_M_cond); /* int __e = */ __gthread_cond_destroy(&_M_cond);
// if __e == EBUSY then blocked // if __e == EBUSY then blocked
} }
#endif
void void
condition_variable::wait(unique_lock<mutex>& __lock) condition_variable::wait(unique_lock<mutex>& __lock)
...@@ -60,7 +60,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -60,7 +60,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
void void
condition_variable::notify_one() condition_variable::notify_one() noexcept
{ {
int __e = __gthread_cond_signal(&_M_cond); int __e = __gthread_cond_signal(&_M_cond);
...@@ -71,7 +71,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -71,7 +71,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
void void
condition_variable::notify_all() condition_variable::notify_all() noexcept
{ {
int __e = __gthread_cond_broadcast(&_M_cond); int __e = __gthread_cond_broadcast(&_M_cond);
...@@ -81,11 +81,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -81,11 +81,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_system_error(__e); __throw_system_error(__e);
} }
condition_variable_any::condition_variable_any() throw () condition_variable_any::condition_variable_any() noexcept = default;
{ }
condition_variable_any::~condition_variable_any() throw () condition_variable_any::~condition_variable_any() noexcept = default;
{ }
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} // namespace } // namespace
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment