From patchwork Mon Oct 24 23:26:35 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 121454 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id F230A1007D8 for ; Tue, 25 Oct 2011 10:27:04 +1100 (EST) Received: (qmail 12108 invoked by alias); 24 Oct 2011 23:27:01 -0000 Received: (qmail 12084 invoked by uid 22791); 24 Oct 2011 23:26:59 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-ww0-f51.google.com (HELO mail-ww0-f51.google.com) (74.125.82.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 24 Oct 2011 23:26:37 +0000 Received: by wwe32 with SMTP id 32so7977685wwe.8 for ; Mon, 24 Oct 2011 16:26:35 -0700 (PDT) MIME-Version: 1.0 Received: by 10.216.21.74 with SMTP id q52mr3805588weq.36.1319498795459; Mon, 24 Oct 2011 16:26:35 -0700 (PDT) Received: by 10.216.36.78 with HTTP; Mon, 24 Oct 2011 16:26:35 -0700 (PDT) In-Reply-To: References: <20111006151524.663e6761@shotwell> Date: Tue, 25 Oct 2011 00:26:35 +0100 Message-ID: Subject: Re: [v3] use NSDMI in C++11 mutex types From: Jonathan Wakely To: "libstdc++" , gcc-patches Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 + static + typename enable_if::value, void>::type + _S_destroy(_Rm* __mx) + { __gthread_mutex_destroy(__mx); } + + // matches a recursive mutex with a member 'actual' + template + static typename enable_if::type + _S_destroy(_Rm* __mx) + { __gthread_mutex_destroy(&__mx->actual); } + + // matches a gthr-win32.h recursive mutex + template + static typename enable_if::type + _S_destroy(_Rm* __mx) + { + __gthread_mutex_t __tmp; + _S_destroy_win32(&__tmp, __mx); + } + + template + 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 - 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 - static typename enable_if::type - _S_destroy(_Rm* __mx) - { - __gthread_mutex_t __tmp; - _S_destroy_win32(&__tmp, __mx); - } - - // matches a recursive mutex with a member 'actual' - template - static typename enable_if::type - _S_destroy(_Rm* __mx) - { __gthread_mutex_destroy(&__mx->actual); } - - // matches when there's only one mutex type - template - static - typename enable_if::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& __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 __lock(_M_mutex); _M_cond.notify_one(); } void - notify_all() + notify_all() noexcept { lock_guard __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& __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