{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ using __gnu_cxx::__int_traits;
+
namespace
{
// Return the relative duration from (now_s + now_ns) to (abs_s + abs_ns)
return rt;
}
- auto rel_s = abs_s.count() - now_s;
-
- // Avoid overflows
- if (rel_s > __gnu_cxx::__int_traits<time_t>::__max)
- rel_s = __gnu_cxx::__int_traits<time_t>::__max;
- else if (rel_s < __gnu_cxx::__int_traits<time_t>::__min)
- rel_s = __gnu_cxx::__int_traits<time_t>::__min;
+ const auto rel_s = abs_s.count() - now_s;
- // Convert the absolute timeout value to a relative timeout
- rt.tv_sec = rel_s;
- rt.tv_nsec = abs_ns.count() - now_ns;
- if (rt.tv_nsec < 0)
+ // Convert the absolute timeout to a relative timeout, without overflow.
+ if (rel_s > __int_traits<time_t>::__max) [[unlikely]]
{
- rt.tv_nsec += 1000000000;
- --rt.tv_sec;
+ rt.tv_sec = __int_traits<time_t>::__max;
+ rt.tv_nsec = 999999999;
+ }
+ else
+ {
+ rt.tv_sec = rel_s;
+ rt.tv_nsec = abs_ns.count() - now_ns;
+ if (rt.tv_nsec < 0)
+ {
+ rt.tv_nsec += 1000000000;
+ --rt.tv_sec;
+ }
}
return rt;
--- /dev/null
+// { dg-do run }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-require-effective-target c++11 }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2020 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
+// <http://www.gnu.org/licenses/>.
+
+
+#include <future>
+#include <chrono>
+#include <climits>
+#include <testsuite_hooks.h>
+
+namespace chrono = std::chrono;
+
+void test01()
+{
+ std::future<void> fut = std::async(std::launch::async, [] {
+ std::this_thread::sleep_for(chrono::seconds(4));
+ });
+
+ // A time in the distant future, but which overflows 32-bit time_t:
+ auto then = chrono::system_clock::now() + chrono::seconds(UINT_MAX + 2LL);
+ auto status = fut.wait_until(then);
+ // The wait_until call should have waited for the result to be ready.
+ // If converting the time_point to time_t overflows, it will timeout.
+ VERIFY(status == std::future_status::ready);
+}
+
+int main()
+{
+ test01();
+}