libstdc++: Fix try_lock_until and try_lock_shared_until on arbitrary clock
This is the equivalent to PR libstdc++/91906, but for shared_mutex. A non-standard clock may tick more slowly than std::chrono::steady_clock. This means that we risk returning false early when the specified timeout may not have expired. This can be avoided by looping until the timeout time as reported by the non-standard clock has been reached. Unfortunately, we have no way to tell whether the non-standard clock ticks more quickly that std::chrono::steady_clock. If it does then we risk returning later than would be expected, but that is unavoidable without waking up periodically to check, which would be rather too expensive. François Dumont pointed out[1] a flaw in an earlier version of this patch that revealed a hole in the test coverage, so I've added a new test that try_lock_until acts as try_lock if the timeout has already expired. [1] https://gcc.gnu.org/ml/libstdc++/2019-10/msg00021.html 2019-12-02 Mike Crowe <mac@mcrowe.com> Fix try_lock_until and try_lock_shared_until on arbitrary clock * include/std/shared_mutex (shared_timed_mutex::try_lock_until) (shared_timed_mutex::try_lock_shared_until): Loop until the absolute timeout time is reached as measured against the appropriate clock. * testsuite/30_threads/shared_timed_mutex/try_lock_until/1.cc: New file. Test try_lock_until and try_lock_shared_until timeouts against various clocks. * testsuite/30_threads/shared_timed_mutex/try_lock_until/1.cc: New file. Test try_lock_until and try_lock_shared_until timeouts against various clocks. From-SVN: r278904
This commit is contained in:
parent
ab40695a46
commit
b789efeae8
@ -1,5 +1,16 @@
|
|||||||
2019-12-02 Mike Crowe <mac@mcrowe.com>
|
2019-12-02 Mike Crowe <mac@mcrowe.com>
|
||||||
|
|
||||||
|
Fix try_lock_until and try_lock_shared_until on arbitrary clock
|
||||||
|
* include/std/shared_mutex (shared_timed_mutex::try_lock_until)
|
||||||
|
(shared_timed_mutex::try_lock_shared_until): Loop until the absolute
|
||||||
|
timeout time is reached as measured against the appropriate clock.
|
||||||
|
* testsuite/30_threads/shared_timed_mutex/try_lock_until/1.cc: New
|
||||||
|
file. Test try_lock_until and try_lock_shared_until timeouts against
|
||||||
|
various clocks.
|
||||||
|
* testsuite/30_threads/shared_timed_mutex/try_lock_until/1.cc: New
|
||||||
|
file. Test try_lock_until and try_lock_shared_until timeouts against
|
||||||
|
various clocks.
|
||||||
|
|
||||||
Add full steady_clock support to shared_timed_mutex
|
Add full steady_clock support to shared_timed_mutex
|
||||||
* acinclude.m4 (GLIBCXX_CHECK_PTHREAD_RWLOCK_CLOCKLOCK): Define
|
* acinclude.m4 (GLIBCXX_CHECK_PTHREAD_RWLOCK_CLOCKLOCK): Define
|
||||||
to check for the presence of both pthread_rwlock_clockrdlock and
|
to check for the presence of both pthread_rwlock_clockrdlock and
|
||||||
|
@ -554,9 +554,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
bool
|
bool
|
||||||
try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
|
try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
|
||||||
{
|
{
|
||||||
|
// The user-supplied clock may not tick at the same rate as
|
||||||
|
// steady_clock, so we must loop in order to guarantee that
|
||||||
|
// the timeout has expired before returning false.
|
||||||
typename _Clock::time_point __now = _Clock::now();
|
typename _Clock::time_point __now = _Clock::now();
|
||||||
auto __rtime = __atime - __now;
|
do {
|
||||||
return try_lock_for(__rtime);
|
auto __rtime = __atime - __now;
|
||||||
|
if (try_lock_for(__rtime))
|
||||||
|
return true;
|
||||||
|
__now = _Clock::now();
|
||||||
|
} while (__atime > __now);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shared ownership
|
// Shared ownership
|
||||||
@ -631,9 +639,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
try_lock_shared_until(const chrono::time_point<_Clock,
|
try_lock_shared_until(const chrono::time_point<_Clock,
|
||||||
_Duration>& __atime)
|
_Duration>& __atime)
|
||||||
{
|
{
|
||||||
|
// The user-supplied clock may not tick at the same rate as
|
||||||
|
// steady_clock, so we must loop in order to guarantee that
|
||||||
|
// the timeout has expired before returning false.
|
||||||
typename _Clock::time_point __now = _Clock::now();
|
typename _Clock::time_point __now = _Clock::now();
|
||||||
auto __rtime = __atime - __now;
|
do {
|
||||||
return try_lock_shared_for(__rtime);
|
auto __rtime = __atime - __now;
|
||||||
|
if (try_lock_shared_for(__rtime))
|
||||||
|
return true;
|
||||||
|
__now = _Clock::now();
|
||||||
|
} while (__atime > __now);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK)
|
#else // ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK)
|
||||||
|
Loading…
Reference in New Issue
Block a user