From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 107865 invoked by alias); 28 Sep 2019 08:48:38 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 97525 invoked by uid 89); 28 Sep 2019 08:48:27 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-22.9 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_SHORT autolearn=ham version=3.3.1 spammy= X-HELO: eggs.gnu.org Received: from eggs.gnu.org (HELO eggs.gnu.org) (209.51.188.92) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 28 Sep 2019 08:48:25 +0000 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iE8Os-00009S-Gq for gcc-patches@gcc.gnu.org; Sat, 28 Sep 2019 04:48:24 -0400 Received: from avasout06.plus.net ([212.159.14.18]:58334) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1iE8Os-00006V-AD for gcc-patches@gcc.gnu.org; Sat, 28 Sep 2019 04:48:22 -0400 Received: from deneb ([80.229.24.9]) by smtp with ESMTP id E8LtikKzlDGRHE8LuiiJKM; Sat, 28 Sep 2019 09:45:18 +0100 X-Clacks-Overhead: "GNU Terry Pratchett" X-CM-Score: 0.00 Received: from mac by deneb with local (Exim 4.92) (envelope-from ) id 1iE8Lj-0006UW-FZ; Sat, 28 Sep 2019 09:45:07 +0100 From: Mike Crowe To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Mike Crowe Subject: [PATCH 11/11] shared_mutex: Fix try_lock_until and try_lock_shared_until on arbitrary clock Date: Sat, 28 Sep 2019 08:48:00 -0000 Message-Id: <45929ebf94945c38491438f3fbe3a94f5e10999f.1569660153.git-series.mac@mcrowe.com> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 212.159.14.18 X-SW-Source: 2019-09/txt/msg01653.txt.bz2 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. * include/std/shared_mutex (try_lock_until, try_lock_shared_until): Loop until the absolute timeout time is reached as measured against the appropriate clock. * testsuite/30_threads/shared_mutex/try_lock_until/1.cc: New file. Test shared_mutex::try_lock_until and shared_mutex::try_lock_shared_until timeouts against various clocks. --- libstdc++-v3/include/std/shared_mutex | 28 ++++++++++++++++++----- libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock_until/1.cc | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock_until/1.cc diff --git a/libstdc++-v3/include/std/shared_mutex b/libstdc++-v3/include/std/shared_mutex index 6e67324..40d45a1 100644 --- a/libstdc++-v3/include/std/shared_mutex +++ b/libstdc++-v3/include/std/shared_mutex @@ -554,9 +554,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) { - typename _Clock::time_point __now = _Clock::now(); - auto __rtime = __atime - __now; - return try_lock_for(__rtime); + // 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(); + while (__atime > __now) { + auto __rtime = __atime - __now; + if (try_lock_for(__rtime)) + return true; + __now = _Clock::now(); + } + return false; } // Shared ownership @@ -631,9 +639,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __atime) { - typename _Clock::time_point __now = _Clock::now(); - auto __rtime = __atime - __now; - return try_lock_shared_for(__rtime); + // 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(); + while (__atime > __now) { + auto __rtime = __atime - __now; + if (try_lock_shared_for(__rtime)) + return true; + __now = _Clock::now(); + } + return false; } #else // ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) diff --git a/libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock_until/1.cc b/libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock_until/1.cc new file mode 100644 index 0000000..77baad9 --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/shared_mutex/try_lock_until/1.cc @@ -0,0 +1,87 @@ +// { dg-do run } +// { dg-options "-pthread" } +// { dg-require-effective-target c++14 } +// { dg-require-effective-target pthread } +// { dg-require-gthreads "" } + +// Copyright (C) 2013-2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + + +#include +#include +#include +#include +#include + +template +void test() +{ + typedef std::shared_timed_mutex mutex_type; + + try + { + mutex_type m; + m.lock(); + bool b; + + std::thread t([&] { + try + { + using namespace std::chrono; + const auto timeout = 100ms; + + { + const auto start = clock_type::now(); + const auto b = m.try_lock_until(start + timeout); + const auto t = clock_type::now() - start; + VERIFY( !b ); + VERIFY( t >= timeout ); + } + + { + const auto start = clock_type::now(); + const auto b = m.try_lock_shared_until(start + timeout); + const auto t = clock_type::now() - start; + VERIFY( !b ); + VERIFY( t >= timeout ); + } + } + catch (const std::system_error& e) + { + VERIFY( false ); + } + }); + t.join(); + m.unlock(); + } + catch (const std::system_error& e) + { + VERIFY( false ); + } + catch (...) + { + VERIFY( false ); + } +} + +int main() +{ + test(); + test(); + test(); +} -- git-series 0.9.1