From 25e00ab67444a01dce446e95308521d1a73f8232 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 18 Jun 2013 22:55:02 +0000 Subject: re PR libstdc++/57641 (std::timed_mutex.try_lock_until() is broken) PR libstdc++/57641 * include/std/mutex (timed_mutex, recursive_timed_mutex): Move common functionality to new __timed_mutex_impl mixin. Overload try_lock_until to handle conversion between different clocks. Replace constrained __try_lock_for_impl overloads with conditional increment. * include/std/shared_mutex (shared_mutex::_Mutex): Use the new mixin. * testsuite/30_threads/timed_mutex/try_lock_until/57641.cc: New. From-SVN: r200180 --- libstdc++-v3/include/std/mutex | 142 ++++++++++++++++------------------------- 1 file changed, 54 insertions(+), 88 deletions(-) (limited to 'libstdc++-v3/include/std/mutex') diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex index cdd05a37cbe..40b2e31dc7f 100644 --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -199,15 +199,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #if _GTHREAD_USE_MUTEX_TIMEDLOCK - /// timed_mutex - class timed_mutex : private __mutex_base - { + template + class __timed_mutex_impl + { + protected: #ifdef _GLIBCXX_USE_CLOCK_MONOTONIC - typedef chrono::steady_clock __clock_t; + typedef chrono::steady_clock __clock_t; #else - typedef chrono::high_resolution_clock __clock_t; + typedef chrono::high_resolution_clock __clock_t; #endif + template + bool + _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime); + if (ratio_greater<__clock_t::period, _Period>()) + ++__rt; + + return _M_try_lock_until(__clock_t::now() + __rt); + } + + template + bool + _M_try_lock_until(const chrono::time_point<__clock_t, + _Duration>& __atime) + { + chrono::time_point<__clock_t, chrono::seconds> __s = + chrono::time_point_cast(__atime); + + chrono::nanoseconds __ns = + chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + auto __mutex = static_cast<_Derived*>(this)->native_handle(); + return !__gthread_mutex_timedlock(__mutex, &__ts); + } + + template + bool + _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { return _M_try_lock_for(__atime - _Clock::now()); } + }; + + /// timed_mutex + class timed_mutex + : private __mutex_base, public __timed_mutex_impl + { public: typedef __native_type* native_handle_type; @@ -237,25 +279,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template bool try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) - { return __try_lock_for_impl(__rtime); } + { return _M_try_lock_for(__rtime); } template bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) - { - chrono::time_point<_Clock, chrono::seconds> __s = - chrono::time_point_cast(__atime); - - chrono::nanoseconds __ns = - chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - return !__gthread_mutex_timedlock(&_M_mutex, &__ts); - } + { return _M_try_lock_until(__atime); } void unlock() @@ -267,40 +296,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION native_handle_type native_handle() { return &_M_mutex; } - - private: - template - 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 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 : private __recursive_mutex_base + class recursive_timed_mutex + : private __recursive_mutex_base, + public __timed_mutex_impl { -#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC - typedef chrono::steady_clock __clock_t; -#else - typedef chrono::high_resolution_clock __clock_t; -#endif - public: typedef __native_type* native_handle_type; @@ -330,25 +332,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template bool try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) - { return __try_lock_for_impl(__rtime); } + { return _M_try_lock_for(__rtime); } template bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) - { - chrono::time_point<_Clock, chrono::seconds> __s = - chrono::time_point_cast(__atime); - - chrono::nanoseconds __ns = - chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); - } + { return _M_try_lock_until(__atime); } void unlock() @@ -360,29 +349,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION native_handle_type native_handle() { return &_M_mutex; } - - private: - template - 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 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); - } }; #endif #endif // _GLIBCXX_HAS_GTHREADS -- cgit v1.2.1