libstdc++: Define and use chrono::is_clock for C++20

For C++20 the wait_until members of mutexes and condition variables are
required to be ill-formed if given a clock that doesn't meet the
requirements for a clock type. To implement that requirement this patch
adds static assertions using the chrono::is_clock trait, and defines
that trait.

To avoid expensive checks for the common cases, the trait (and
associated variable template) are explicitly specialized for the
standard clock types.

This also moves the filesystem::__file_clock type from <filesystem> to
<chrono>, so that chrono::file_clock and chrono::file_time can be
defined in <chrono> as required.

	* include/bits/fs_fwd.h (filesystem::__file_clock): Move to ...
	* include/std/chrono (filesystem::__file_clock): Here.
	(filesystem::__file_clock::from_sys, filesystem::__file_clock::to_sys):
	Define public member functions for C++20.
	(is_clock, is_clock_v): Define traits for C++20.
	* include/std/condition_variable (condition_variable::wait_until): Add
	check for valid clock.
	* include/std/future (_State_baseV2::wait_until): Likewise.
	* include/std/mutex (__timed_mutex_impl::_M_try_lock_until): Likewise.
	* include/std/shared_mutex (shared_timed_mutex::try_lock_shared_until):
	Likewise.
	* include/std/thread (this_thread::sleep_until): Likewise.
	* testsuite/30_threads/condition_variable/members/2.cc: Qualify
	slow_clock with new namespace.
	* testsuite/30_threads/condition_variable/members/clock_neg.cc: New
	test.
	* testsuite/30_threads/condition_variable_any/members/clock_neg.cc:
	New test.
	* testsuite/30_threads/future/members/clock_neg.cc: New test.
	* testsuite/30_threads/recursive_timed_mutex/try_lock_until/3.cc:
	Qualify slow_clock with new namespace.
	* testsuite/30_threads/recursive_timed_mutex/try_lock_until/
	clock_neg.cc: New test.
	* testsuite/30_threads/shared_future/members/clock_neg.cc: New
	test.
	* testsuite/30_threads/shared_lock/locking/clock_neg.cc: New test.
	* testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc:
	New test.
	* testsuite/30_threads/timed_mutex/try_lock_until/3.cc: Qualify
	slow_clock with new namespace.
	* testsuite/30_threads/timed_mutex/try_lock_until/4.cc: Likewise.
	* testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc: New
	test.
	* testsuite/30_threads/unique_lock/locking/clock_neg.cc: New test.
	* testsuite/std/time/traits/is_clock.cc: New test.
	* testsuite/util/slow_clock.h (slow_clock): Move to __gnu_test
	namespace.
This commit is contained in:
Jonathan Wakely 2020-03-25 22:07:02 +00:00
parent fe4b53b2e7
commit bf1fc37bb4
23 changed files with 861 additions and 45 deletions

View file

@ -1,3 +1,43 @@
2020-03-25 Jonathan Wakely <jwakely@redhat.com>
* include/bits/fs_fwd.h (filesystem::__file_clock): Move to ...
* include/std/chrono (filesystem::__file_clock): Here.
(filesystem::__file_clock::from_sys, filesystem::__file_clock::to_sys):
Define public member functions for C++20.
(is_clock, is_clock_v): Define traits for C++20.
* include/std/condition_variable (condition_variable::wait_until): Add
check for valid clock.
* include/std/future (_State_baseV2::wait_until): Likewise.
* include/std/mutex (__timed_mutex_impl::_M_try_lock_until): Likewise.
* include/std/shared_mutex (shared_timed_mutex::try_lock_shared_until):
Likewise.
* include/std/thread (this_thread::sleep_until): Likewise.
* testsuite/30_threads/condition_variable/members/2.cc: Qualify
slow_clock with new namespace.
* testsuite/30_threads/condition_variable/members/clock_neg.cc: New
test.
* testsuite/30_threads/condition_variable_any/members/clock_neg.cc:
New test.
* testsuite/30_threads/future/members/clock_neg.cc: New test.
* testsuite/30_threads/recursive_timed_mutex/try_lock_until/3.cc:
Qualify slow_clock with new namespace.
* testsuite/30_threads/recursive_timed_mutex/try_lock_until/
clock_neg.cc: New test.
* testsuite/30_threads/shared_future/members/clock_neg.cc: New
test.
* testsuite/30_threads/shared_lock/locking/clock_neg.cc: New test.
* testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc:
New test.
* testsuite/30_threads/timed_mutex/try_lock_until/3.cc: Qualify
slow_clock with new namespace.
* testsuite/30_threads/timed_mutex/try_lock_until/4.cc: Likewise.
* testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc: New
test.
* testsuite/30_threads/unique_lock/locking/clock_neg.cc: New test.
* testsuite/std/time/traits/is_clock.cc: New test.
* testsuite/util/slow_clock.h (slow_clock): Move to __gnu_test
namespace.
2020-03-21 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/93245

View file

@ -291,48 +291,6 @@ _GLIBCXX_END_NAMESPACE_CXX11
operator^=(directory_options& __x, directory_options __y) noexcept
{ return __x = __x ^ __y; }
struct __file_clock
{
using duration = chrono::nanoseconds;
using rep = duration::rep;
using period = duration::period;
using time_point = chrono::time_point<__file_clock>;
static constexpr bool is_steady = false;
static time_point
now() noexcept
{ return _S_from_sys(chrono::system_clock::now()); }
private:
using __sys_clock = chrono::system_clock;
// This clock's (unspecified) epoch is 2174-01-01 00:00:00 UTC.
// A signed 64-bit duration with nanosecond resolution gives roughly
// +/- 292 years, which covers the 1901-2446 date range for ext4.
static constexpr chrono::seconds _S_epoch_diff{6437664000};
protected:
// For internal use only
template<typename _Dur>
static
chrono::time_point<__file_clock, _Dur>
_S_from_sys(const chrono::time_point<__sys_clock, _Dur>& __t) noexcept
{
using __file_time = chrono::time_point<__file_clock, _Dur>;
return __file_time{__t.time_since_epoch()} - _S_epoch_diff;
}
// For internal use only
template<typename _Dur>
static
chrono::time_point<__sys_clock, _Dur>
_S_to_sys(const chrono::time_point<__file_clock, _Dur>& __t) noexcept
{
using __sys_time = chrono::time_point<__sys_clock, _Dur>;
return __sys_time{__t.time_since_epoch()} + _S_epoch_diff;
}
};
using file_time_type = __file_clock::time_point;
// operational functions

View file

@ -41,11 +41,18 @@
#include <limits>
#include <ctime>
#include <bits/parse_numbers.h> // for literals support.
#if __cplusplus > 201703L
# include <concepts>
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201703L
namespace filesystem { struct __file_clock; };
#endif
/**
* @defgroup chrono Time
* @ingroup utilities
@ -237,6 +244,60 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
treat_as_floating_point<_Rep>::value;
#endif // C++17
#if __cplusplus > 201703L
template<typename _Tp>
struct is_clock;
template<typename _Tp>
inline constexpr bool is_clock_v = is_clock<_Tp>::value;
#if __cpp_lib_concepts
template<typename _Tp>
struct is_clock : false_type
{ };
template<typename _Tp>
requires requires {
typename _Tp::rep;
typename _Tp::period;
typename _Tp::duration;
typename _Tp::time_point::clock;
typename _Tp::time_point::duration;
{ &_Tp::is_steady } -> same_as<const bool*>;
{ _Tp::now() } -> same_as<typename _Tp::time_point>;
requires same_as<typename _Tp::duration,
duration<typename _Tp::rep, typename _Tp::period>>;
requires same_as<typename _Tp::time_point::duration,
typename _Tp::duration>;
}
struct is_clock<_Tp> : true_type
{ };
#else
template<typename _Tp, typename = void>
struct __is_clock_impl : false_type
{ };
template<typename _Tp>
struct __is_clock_impl<_Tp,
void_t<typename _Tp::rep, typename _Tp::period,
typename _Tp::duration,
typename _Tp::time_point::duration,
decltype(_Tp::is_steady),
decltype(_Tp::now())>>
: __and_<is_same<typename _Tp::duration,
duration<typename _Tp::rep, typename _Tp::period>>,
is_same<typename _Tp::time_point::duration,
typename _Tp::duration>,
is_same<decltype(&_Tp::is_steady), const bool*>,
is_same<decltype(_Tp::now()), typename _Tp::time_point>>::type
{ };
template<typename _Tp>
struct is_clock : __is_clock_impl<_Tp>::type
{ };
#endif
#endif // C++20
#if __cplusplus >= 201703L
# define __cpp_lib_chrono 201611
@ -948,6 +1009,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using high_resolution_clock = system_clock;
} // end inline namespace _V2
#if __cplusplus > 201703L
template<typename _Duration>
using sys_time = time_point<system_clock, _Duration>;
using sys_seconds = sys_time<seconds>;
using file_clock = ::std::filesystem::__file_clock;
template<typename _Duration>
using file_time = time_point<file_clock, _Duration>;
template<> struct is_clock<system_clock> : true_type { };
template<> struct is_clock<steady_clock> : true_type { };
template<> struct is_clock<file_clock> : true_type { };
template<> inline constexpr bool is_clock_v<system_clock> = true;
template<> inline constexpr bool is_clock_v<steady_clock> = true;
template<> inline constexpr bool is_clock_v<file_clock> = true;
#endif // C++20
// @}
} // namespace chrono
@ -1071,6 +1152,67 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using namespace literals::chrono_literals;
} // namespace chrono
#if __cplusplus >= 201703L
namespace filesystem
{
struct __file_clock
{
using duration = chrono::nanoseconds;
using rep = duration::rep;
using period = duration::period;
using time_point = chrono::time_point<__file_clock>;
static constexpr bool is_steady = false;
static time_point
now() noexcept
{ return _S_from_sys(chrono::system_clock::now()); }
#if __cplusplus > 201703L
template<typename _Dur>
static
chrono::file_time<_Dur>
from_sys(const chrono::sys_time<_Dur>& __t) noexcept
{ return _S_from_sys(__t); }
// For internal use only
template<typename _Dur>
static
chrono::sys_time<_Dur>
to_sys(const chrono::file_time<_Dur>& __t) noexcept
{ return _S_to_sys(__t); }
#endif // C++20
private:
using __sys_clock = chrono::system_clock;
// This clock's (unspecified) epoch is 2174-01-01 00:00:00 UTC.
// A signed 64-bit duration with nanosecond resolution gives roughly
// +/- 292 years, which covers the 1901-2446 date range for ext4.
static constexpr chrono::seconds _S_epoch_diff{6437664000};
protected:
// For internal use only
template<typename _Dur>
static
chrono::time_point<__file_clock, _Dur>
_S_from_sys(const chrono::time_point<__sys_clock, _Dur>& __t) noexcept
{
using __file_time = chrono::time_point<__file_clock, _Dur>;
return __file_time{__t.time_since_epoch()} - _S_epoch_diff;
}
// For internal use only
template<typename _Dur>
static
chrono::time_point<__sys_clock, _Dur>
_S_to_sys(const chrono::time_point<__file_clock, _Dur>& __t) noexcept
{
using __sys_time = chrono::time_point<__sys_clock, _Dur>;
return __sys_time{__t.time_since_epoch()} + _S_epoch_diff;
}
};
} // namespace filesystem
#endif // C++17
#endif // C++14
_GLIBCXX_END_NAMESPACE_VERSION

View file

@ -131,6 +131,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
wait_until(unique_lock<mutex>& __lock,
const chrono::time_point<_Clock, _Duration>& __atime)
{
#if __cplusplus > 201703L
static_assert(chrono::is_clock_v<_Clock>);
#endif
const typename _Clock::time_point __c_entry = _Clock::now();
const __clock_t::time_point __s_entry = __clock_t::now();
const auto __delta = __atime - __c_entry;

View file

@ -371,6 +371,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
future_status
wait_until(const chrono::time_point<_Clock, _Duration>& __abs)
{
#if __cplusplus > 201703L
static_assert(chrono::is_clock_v<_Clock>);
#endif
// First, check if the future has been made ready. Use acquire MO
// to synchronize with the thread that made it ready.
if (_M_status._M_load(memory_order_acquire) == _Status::__ready)

View file

@ -189,6 +189,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool
_M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
{
#if __cplusplus > 201703L
static_assert(chrono::is_clock_v<_Clock>);
#endif
// 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.

View file

@ -554,6 +554,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool
try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
{
#if __cplusplus > 201703L
static_assert(chrono::is_clock_v<_Clock>);
#endif
// 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.
@ -639,6 +642,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
try_lock_shared_until(const chrono::time_point<_Clock,
_Duration>& __atime)
{
#if __cplusplus > 201703L
static_assert(chrono::is_clock_v<_Clock>);
#endif
// 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.

View file

@ -414,6 +414,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void
sleep_until(const chrono::time_point<_Clock, _Duration>& __atime)
{
#if __cplusplus > 201703L
static_assert(chrono::is_clock_v<_Clock>);
#endif
auto __now = _Clock::now();
if (_Clock::is_steady)
{

View file

@ -55,6 +55,8 @@ void test01()
void test01_alternate_clock()
{
using __gnu_test::slow_clock;
try
{
std::condition_variable c1;

View file

@ -0,0 +1,61 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <condition_variable>
struct clok
{
// no clok::rep or clok::period defined
using duration = std::chrono::milliseconds;
using time_point = std::chrono::time_point<clok>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test01()
{
std::mutex m;
std::unique_lock<std::mutex> l(m);
std::condition_variable cv;
cv.wait_until(l, clok::now()); // { dg-error "here" }
}
struct cloc
{
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
// cloc::time_point::duration should be the same as cloc::duration:
using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test02()
{
std::mutex m;
std::unique_lock<std::mutex> l(m);
std::condition_variable cv;
cv.wait_until(l, cloc::now()); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }

View file

@ -0,0 +1,61 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <condition_variable>
struct clok
{
// no clok::rep or clok::period defined
using duration = std::chrono::milliseconds;
using time_point = std::chrono::time_point<clok>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test01()
{
std::mutex m;
std::unique_lock<std::mutex> l(m);
std::condition_variable_any cv;
cv.wait_until(l, clok::now()); // { dg-error "here" }
}
struct cloc
{
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
// cloc::time_point::duration should be the same as cloc::duration:
using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test02()
{
std::mutex m;
std::unique_lock<std::mutex> l(m);
std::condition_variable_any cv;
cv.wait_until(l, cloc::now()); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }

View file

@ -0,0 +1,59 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <future>
struct clok
{
// no clok::rep or clok::period defined
using duration = std::chrono::milliseconds;
using time_point = std::chrono::time_point<clok>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test01()
{
std::promise<void> p;
std::future<void> f = p.get_future();
f.wait_until(clok::now()); // { dg-error "here" }
}
struct cloc
{
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
// cloc::time_point::duration should be the same as cloc::duration:
using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test02()
{
std::promise<void> p;
std::future<void> f = p.get_future();
f.wait_until(cloc::now()); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }

View file

@ -72,5 +72,5 @@ int main()
{
test<std::chrono::system_clock>();
test<std::chrono::steady_clock>();
test<slow_clock>();
test<__gnu_test::slow_clock>();
}

View file

@ -0,0 +1,57 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <mutex>
struct clok
{
// no clok::rep or clok::period defined
using duration = std::chrono::milliseconds;
using time_point = std::chrono::time_point<clok>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test01()
{
std::recursive_timed_mutex m;
m.try_lock_until(clok::now()); // { dg-error "here" }
}
struct cloc
{
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
// cloc::time_point::duration should be the same as cloc::duration:
using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test02()
{
std::recursive_timed_mutex m;
m.try_lock_until(cloc::now()); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }

View file

@ -0,0 +1,59 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <future>
struct clok
{
// no clok::rep or clok::period defined
using duration = std::chrono::milliseconds;
using time_point = std::chrono::time_point<clok>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test01()
{
std::promise<void> p;
std::shared_future<void> f = p.get_future();
f.wait_until(clok::now()); // { dg-error "here" }
}
struct cloc
{
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
// cloc::time_point::duration should be the same as cloc::duration:
using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test02()
{
std::promise<void> p;
std::shared_future<void> f = p.get_future();
f.wait_until(cloc::now()); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }

View file

@ -0,0 +1,59 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <shared_mutex>
struct clok
{
// no clok::rep or clok::period defined
using duration = std::chrono::milliseconds;
using time_point = std::chrono::time_point<clok>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test01()
{
std::shared_timed_mutex m;
std::shared_lock<std::shared_timed_mutex> l(m, std::defer_lock);
l.try_lock_until(clok::now()); // { dg-error "here" }
}
struct cloc
{
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
// cloc::time_point::duration should be the same as cloc::duration:
using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test02()
{
std::shared_timed_mutex m;
std::shared_lock<std::shared_timed_mutex> l(m, std::defer_lock);
l.try_lock_until(cloc::now()); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }

View file

@ -0,0 +1,57 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <shared_mutex>
struct clok
{
// no clok::rep or clok::period defined
using duration = std::chrono::milliseconds;
using time_point = std::chrono::time_point<clok>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test01()
{
std::shared_timed_mutex m;
m.try_lock_until(clok::now()); // { dg-error "here" }
}
struct cloc
{
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
// cloc::time_point::duration should be the same as cloc::duration:
using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test02()
{
std::shared_timed_mutex m;
m.try_lock_shared_until(cloc::now()); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }

View file

@ -72,5 +72,5 @@ int main()
{
test<std::chrono::system_clock>();
test<std::chrono::steady_clock>();
test<slow_clock>();
test<__gnu_test::slow_clock>();
}

View file

@ -64,5 +64,5 @@ int main()
{
test<std::chrono::system_clock>();
test<std::chrono::steady_clock>();
test<slow_clock>();
test<__gnu_test::slow_clock>();
}

View file

@ -0,0 +1,57 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <mutex>
struct clok
{
// no clok::rep or clok::period defined
using duration = std::chrono::milliseconds;
using time_point = std::chrono::time_point<clok>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test01()
{
std::timed_mutex m;
m.try_lock_until(clok::now()); // { dg-error "here" }
}
struct cloc
{
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
// cloc::time_point::duration should be the same as cloc::duration:
using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test02()
{
std::timed_mutex m;
m.try_lock_until(cloc::now()); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }

View file

@ -0,0 +1,59 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <mutex>
struct clok
{
// no clok::rep or clok::period defined
using duration = std::chrono::milliseconds;
using time_point = std::chrono::time_point<clok>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test01()
{
std::timed_mutex m;
std::unique_lock<std::timed_mutex> l(m, std::defer_lock);
l.try_lock_until(clok::now()); // { dg-error "here" }
}
struct cloc
{
using duration = std::chrono::milliseconds;
using rep = duration::rep;
using period = duration::period;
// cloc::time_point::duration should be the same as cloc::duration:
using time_point = std::chrono::time_point<cloc, std::chrono::seconds>;
static constexpr bool is_steady = false;
static time_point now();
};
void
test02()
{
std::recursive_timed_mutex m;
std::unique_lock<std::recursive_timed_mutex> l(m, std::defer_lock);
l.try_lock_until(cloc::now()); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }

View file

@ -0,0 +1,124 @@
// 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/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
#include <chrono>
#include <slow_clock.h>
namespace chrono = std::chrono;
static_assert( chrono::is_clock<chrono::system_clock>::value );
static_assert( chrono::is_clock_v<chrono::system_clock> );
static_assert( chrono::is_clock<chrono::high_resolution_clock>::value );
static_assert( chrono::is_clock_v<chrono::high_resolution_clock> );
static_assert( chrono::is_clock<chrono::steady_clock>::value );
static_assert( chrono::is_clock_v<chrono::steady_clock> );
static_assert(chrono::is_clock<chrono::file_clock>::value);
static_assert(chrono::is_clock_v<chrono::file_clock>);
static_assert( chrono::is_clock<__gnu_test::slow_clock>::value );
static_assert( chrono::is_clock_v<__gnu_test::slow_clock> );
static_assert( ! chrono::is_clock<int>::value );
static_assert( ! chrono::is_clock_v<int> );
static_assert( ! chrono::is_clock<void>::value );
static_assert( ! chrono::is_clock_v<void> );
struct not_a_clock_1
{
using rep = int;
using period = std::ratio<4, 2>;
using duration = chrono::duration<long, period>; // different rep
using time_point = chrono::time_point<not_a_clock_1>;
static constexpr bool is_steady = false;
static time_point now();
};
static_assert( ! chrono::is_clock<not_a_clock_1>::value );
static_assert( ! chrono::is_clock_v<not_a_clock_1> );
struct not_a_clock_2
{
using rep = int;
using period = int; // not a std::ratio
using duration = chrono::duration<rep>;
using time_point = chrono::time_point<not_a_clock_2>;
static constexpr bool is_steady = false;
static time_point now();
};
static_assert( ! chrono::is_clock<not_a_clock_2>::value );
static_assert( ! chrono::is_clock_v<not_a_clock_2> );
struct not_a_clock_3
{
using rep = int;
using period = std::ratio<1>;
using duration = chrono::duration<rep>;
// wrong duration:
using time_point = chrono::time_point<not_a_clock_3, chrono::duration<long>>;
static constexpr bool is_steady = false;
static time_point now();
};
static_assert( ! chrono::is_clock<not_a_clock_3>::value );
static_assert( ! chrono::is_clock_v<not_a_clock_3> );
struct not_a_clock_4
{
using rep = int;
using period = std::ratio<1>;
using duration = chrono::duration<rep>;
using time_point = chrono::time_point<not_a_clock_4>;
static constexpr int is_steady = 0; // not a const bool
static time_point now();
};
static_assert( ! chrono::is_clock<not_a_clock_4>::value );
static_assert( ! chrono::is_clock_v<not_a_clock_4> );
struct not_a_clock_5
{
using rep = int;
using period = std::ratio<1>;
using duration = chrono::duration<rep>;
using time_point = chrono::time_point<not_a_clock_5>;
static constexpr bool is_steady = false;
static int now(); // wrong return type
};
static_assert( ! chrono::is_clock<not_a_clock_5>::value );
static_assert( ! chrono::is_clock_v<not_a_clock_5> );
struct not_a_clock_6
{
using rep = int;
using period = std::ratio<1>;
using duration = chrono::duration<rep>;
using time_point = chrono::time_point<not_a_clock_6>;
const bool is_steady = false; // not static
static time_point now();
};
static_assert( ! chrono::is_clock<not_a_clock_6>::value );
static_assert( ! chrono::is_clock_v<not_a_clock_6> );

View file

@ -22,6 +22,8 @@
#include <chrono>
namespace __gnu_test
{
struct slow_clock
{
using rep = std::chrono::system_clock::rep;
@ -36,3 +38,4 @@ struct slow_clock
return time_point{real.time_since_epoch() / 3};
}
};
}