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.
Tested x86_64-linux, committed to trunk.
Index: include/std/mutex =================================================================== --- include/std/mutex (revision 180329) +++ include/std/mutex (working copy) @@ -52,6 +52,94 @@ { _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 * @ingroup concurrency @@ -61,25 +149,16 @@ */ /// mutex - class mutex + class mutex : private __mutex_base { - typedef __gthread_mutex_t __native_type; - __native_type _M_mutex; - public: typedef __native_type* native_handle_type; #ifdef __GTHREAD_MUTEX_INIT - constexpr mutex() noexcept : _M_mutex(__GTHREAD_MUTEX_INIT) { } -#else - mutex() noexcept - { - // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) - __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); - } - - ~mutex() { __gthread_mutex_destroy(&_M_mutex); } + constexpr #endif + mutex() noexcept = default; + ~mutex() = default; mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; @@ -113,67 +192,15 @@ { 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 - class recursive_mutex + class recursive_mutex : private __recursive_mutex_base { - typedef __gthread_recursive_mutex_t __native_type; - __native_type _M_mutex; - public: typedef __native_type* native_handle_type; -#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT - recursive_mutex() : _M_mutex(__GTHREAD_RECURSIVE_MUTEX_INIT) { } -#else - recursive_mutex() - { - // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) - __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); - } + recursive_mutex() = default; + ~recursive_mutex() = default; - ~recursive_mutex() - { __destroy_recursive_mutex::_S_destroy(&_M_mutex); } -#endif - recursive_mutex(const recursive_mutex&) = delete; recursive_mutex& operator=(const recursive_mutex&) = delete; @@ -208,32 +235,20 @@ #if _GTHREAD_USE_MUTEX_TIMEDLOCK /// timed_mutex - class timed_mutex + class timed_mutex : private __mutex_base { - typedef __gthread_mutex_t __native_type; - #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC typedef chrono::steady_clock __clock_t; #else typedef chrono::high_resolution_clock __clock_t; #endif - __native_type _M_mutex; - public: typedef __native_type* native_handle_type; -#ifdef __GTHREAD_MUTEX_INIT - timed_mutex() : _M_mutex(__GTHREAD_MUTEX_INIT) { } -#else - timed_mutex() - { - __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); - } + timed_mutex() = default; + ~timed_mutex() = default; - ~timed_mutex() { __gthread_mutex_destroy(&_M_mutex); } -#endif - timed_mutex(const timed_mutex&) = delete; timed_mutex& operator=(const timed_mutex&) = delete; @@ -313,34 +328,20 @@ }; /// 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 typedef chrono::steady_clock __clock_t; #else typedef chrono::high_resolution_clock __clock_t; #endif - __native_type _M_mutex; - public: typedef __native_type* native_handle_type; -#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT - recursive_timed_mutex() : _M_mutex(__GTHREAD_RECURSIVE_MUTEX_INIT) { } -#else - recursive_timed_mutex() - { - // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) - __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); - } + recursive_timed_mutex() = default; + ~recursive_timed_mutex() = default; - ~recursive_timed_mutex() - { __destroy_recursive_mutex::_S_destroy(&_M_mutex); } -#endif - recursive_timed_mutex(const recursive_timed_mutex&) = delete; recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; Index: include/std/condition_variable =================================================================== --- include/std/condition_variable (revision 180329) +++ include/std/condition_variable (working copy) @@ -60,22 +60,27 @@ { typedef chrono::system_clock __clock_t; typedef __gthread_cond_t __native_type; + +#ifdef __GTHREAD_COND_INIT + __native_type _M_cond = __GTHREAD_COND_INIT; +#else __native_type _M_cond; +#endif public: typedef __native_type* native_handle_type; - condition_variable() throw (); - ~condition_variable() throw (); + condition_variable() noexcept; + ~condition_variable() noexcept; condition_variable(const condition_variable&) = delete; condition_variable& operator=(const condition_variable&) = delete; void - notify_one(); + notify_one() noexcept; void - notify_all(); + notify_all() noexcept; void wait(unique_lock<mutex>& __lock); @@ -174,21 +179,21 @@ public: typedef condition_variable::native_handle_type native_handle_type; - condition_variable_any() throw (); - ~condition_variable_any() throw (); + condition_variable_any() noexcept; + ~condition_variable_any() noexcept; condition_variable_any(const condition_variable_any&) = delete; condition_variable_any& operator=(const condition_variable_any&) = delete; void - notify_one() + notify_one() noexcept { lock_guard<mutex> __lock(_M_mutex); _M_cond.notify_one(); } void - notify_all() + notify_all() noexcept { lock_guard<mutex> __lock(_M_mutex); _M_cond.notify_all(); Index: src/condition_variable.cc =================================================================== --- src/condition_variable.cc (revision 180329) +++ src/condition_variable.cc (working copy) @@ -30,25 +30,25 @@ { _GLIBCXX_BEGIN_NAMESPACE_VERSION - condition_variable::condition_variable() throw () - { #ifdef __GTHREAD_COND_INIT - __native_type __tmp = __GTHREAD_COND_INIT; - _M_cond = __tmp; + condition_variable::condition_variable() = default; + condition_variable::~condition_variable() = default; #else + condition_variable::condition_variable() noexcept + { int __e = __gthread_cond_init(&_M_cond, 0); if (__e) __throw_system_error(__e); -#endif } - condition_variable::~condition_variable() throw () + condition_variable::~condition_variable() noexcept { // XXX no thread blocked /* int __e = */ __gthread_cond_destroy(&_M_cond); // if __e == EBUSY then blocked } +#endif void condition_variable::wait(unique_lock<mutex>& __lock) @@ -60,7 +60,7 @@ } void - condition_variable::notify_one() + condition_variable::notify_one() noexcept { int __e = __gthread_cond_signal(&_M_cond); @@ -71,7 +71,7 @@ } void - condition_variable::notify_all() + condition_variable::notify_all() noexcept { int __e = __gthread_cond_broadcast(&_M_cond); @@ -81,11 +81,9 @@ __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 } // namespace