[PATCH] Add C++2a synchronization support
Jonathan Wakely
jwakely@redhat.com
Mon Aug 3 14:09:57 GMT 2020
On 05/06/20 17:29 -0700, Thomas Rodgers wrote:
>diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h
>new file mode 100644
>index 00000000000..f0c4235d91c
>--- /dev/null
>+++ b/libstdc++-v3/include/bits/semaphore_base.h
>@@ -0,0 +1,272 @@
>+// -*- C++ -*- header.
>+
>+// 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.
>+
>+// Under Section 7 of GPL version 3, you are granted additional
>+// permissions described in the GCC Runtime Library Exception, version
>+// 3.1, as published by the Free Software Foundation.
>+
>+// You should have received a copy of the GNU General Public License and
>+// a copy of the GCC Runtime Library Exception along with this program;
>+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
>+// <http://www.gnu.org/licenses/>.
>+
>+/** @file bits/semaphore_base.h
>+ * This is an internal header file, included by other library headers.
>+ * Do not attempt to use it directly. @headername{semaphore}
>+ */
>+
>+#ifndef _GLIBCXX_SEMAPHORE_BASE_H
>+#define _GLIBCXX_SEMAPHORE_BASE_H 1
>+
>+#pragma GCC system_header
>+
>+#include <bits/c++config.h>
>+#include <bits/atomic_base.h>
>+#include <bits/atomic_timed_wait.h>
>+
>+#if defined _POSIX_SEMAPHORES && __has_include(<semaphore.h>)
>+#define _GLIBCXX_HAVE_POSIX_SEMAPHORE 1
>+#include <semaphore.h>
>+#endif
>+
>+#include <chrono>
>+#include <type_traits>
>+
>+namespace std _GLIBCXX_VISIBILITY(default)
>+{
>+_GLIBCXX_BEGIN_NAMESPACE_VERSION
>+
>+#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
>+ template<ptrdiff_t __least_max_value>
>+ struct __platform_semaphore
>+ {
I think we want to delete the copy constructor and copy assignment
operator for this type and __atomic_semaphore.
>+ using __clock_t = chrono::system_clock;
>+
>+ explicit __platform_semaphore(ptrdiff_t __count) noexcept
>+ {
>+ static_assert( __least_max_value <= SEM_VALUE_MAX, "");
>+ auto __e = sem_init(&_M_semaphore, 0, __count);
>+ if (__e)
>+ std::terminate();
I don't think we should bother checking the return value. The failure
conditions are EINVAL if __count > SEM_VALUE_MAX, and ENOSYS if the
second argument is non-zero. Both conditions should be impossible.
>+ }
>+
>+ ~__platform_semaphore()
>+ {
>+ auto __e = sem_destroy(&_M_semaphore);
>+ if (__e)
>+ std::terminate();
Likewise here. The only error condition is EINVAL, which is impossible
if _M_semaphore is a valid semaphore, which the constructor already
ensured.
If somehow _M_semaphore is invalid it means the user broke something
(e.g. by scribbling over *this) and we don't need to detect and handle
that case.
>+ }
>+
>+ _GLIBCXX_ALWAYS_INLINE void
>+ acquire() noexcept
>+ {
>+ auto __err = sem_wait(&_M_semaphore);
>+ if (__err)
>+ std::terminate();
What about the EINTR case where the wait is interrupted by a signal?
I think that should retry, but it shouldn't terminate.
>+ template<typename _Duration>
>+ bool
>+ __try_acquire_until_impl(const chrono::time_point<__clock_t>& __atime) noexcept
>+ {
>+ auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
>+ auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
>+
>+ struct timespec __ts =
>+ {
>+ static_cast<std::time_t>(__s.time_since_epoch().count()),
>+ static_cast<long>(__ns.count())
>+ };
>+
>+ auto __err = sem_timedwait(&_M_semaphore, &__ts);
>+ if (__err && (errno == ETIMEDOUT))
>+ return false;
>+ else if (__err)
>+ std::terminate();
I think this needs to handle both EINTR and EINVAL:
EINVAL The value of abs_timeout.tv_nsecs is less than 0, or greater than or equal to 1000 million.
Alternatively, just return immediately without waiting for a time
before the epoch, i.e. __abs_time < time_point<__clock_t>{}
Otherwise time_point(-20ns) will cause EINVAL and terminate.
>+ return true;
>+ }
>+
>+ template<typename _Clock, typename _Duration>
>+ bool
>+ try_acquire_until(const chrono::time_point<_Clock, _Duration>& __atime) noexcept
>+ {
>+ if constexpr (std::is_same<__clock_t, _Clock>::value)
>+ {
>+ return __try_acquire_until_impl(__atime);
>+ }
>+ else
>+ {
>+ const typename _Clock::time_point __c_entry = _Clock::now();
>+ const __clock_t __s_entry = __clock_t::now();
>+ const auto __delta = __atime - __c_entry;
>+ const auto __s_atime = __s_entry + __delta;
>+ if (__try_acquire_until_impl(__s_atime))
>+ return true;
>+
>+ // We got a timeout when measured against __clock_t but
>+ // we need to check against the caller-supplied clock
>+ // to tell whether we should return a timeout.
>+ return (_Clock::now() < __atime);
>+ }
>+ }
>+
>+ template<typename _Rep, typename _Period>
>+ _GLIBCXX_ALWAYS_INLINE bool
>+ try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) noexcept
>+ { return try_acquire_until(__clock_t::now() + __rtime); }
>+
>+ template<typename _Clock, typename _Duration>
>+ _GLIBCXX_ALWAYS_INLINE void
>+ release(ptrdiff_t __update) noexcept
>+ {
>+ do
>+ {
>+ auto __err = sem_post(&_M_semaphore);
>+ if (__err)
>+ std::terminate();
>+ } while (--__update);
>+ }
>+
>+ private:
>+ sem_t _M_semaphore;
>+ };
>+#endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE
>+
>+ template<typename _Tp>
>+ struct __atomic_semaphore
>+ {
Do we want a static_assert(is_integral_v<_Tp>) or similar?
>+ explicit __atomic_semaphore(_Tp __count)
Add noexcept?
>+ : _M_a(__count)
>+ { }
>+
>+ _GLIBCXX_ALWAYS_INLINE void
>+ acquire() noexcept
>+ {
>+ auto const __pred = [this]
>+ {
>+ auto __old = __atomic_impl::load(&this->_M_a,
>+ memory_order::acquire);
Would it be simpler to just use a local atomic_ref to manipulate _M_a
here, and in the other members performing atomic ops on that member?
>+ if (__old == 0)
>+ return false;
>+ return __atomic_impl::compare_exchange_strong(&this->_M_a,
>+ __old, __old - 1,
>+ memory_order::acquire,
>+ memory_order::release);
>+ };
>+ auto __old = __atomic_impl::load(&_M_a, memory_order_relaxed);
>+ __atomic_wait(&_M_a, __old, __pred);
Strictly speaking, this __atomic_wait would violate the "all accesses
to that object shall exclusively occur through those atomic_ref
instances" rule. But we know that it's actually OK because
__atomic_wait is only performing atomic ops on the same location.
>+ }
>+
>+ bool
>+ try_acquire() noexcept
>+ {
>+ auto __old = __atomic_impl::load(&_M_a, memory_order::acquire);
>+ if (__old == 0)
>+ return false;
>+
>+ return __atomic_spin([this, &__old]
>+ {
>+ return __atomic_impl::compare_exchange_weak(&this->_M_a,
>+ __old, __old - 1,
>+ memory_order::acquire,
>+ memory_order::release);
>+ });
>+ }
>+
>+ template<typename _Clock, typename _Duration>
>+ _GLIBCXX_ALWAYS_INLINE bool
>+ try_acquire_until(const chrono::time_point<_Clock, _Duration>& __atime) noexcept
>+ {
>+ auto const __pred = [this]
>+ {
>+ auto __old = __atomic_impl::load(&this->_M_a,
>+ memory_order::acquire);
>+ if (__old == 0)
>+ return false;
>+ return __atomic_impl::compare_exchange_strong(&this->_M_a,
>+ __old, __old - 1,
>+ memory_order::acquire,
>+ memory_order::release);
>+ };
>+
>+ auto __old = __atomic_impl::load(&_M_a, memory_order_relaxed);
>+ return __atomic_wait_until(&_M_a, __old, __pred, __atime);
>+ }
>+
>+ template<typename _Rep, typename _Period>
>+ _GLIBCXX_ALWAYS_INLINE bool
>+ try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) noexcept
>+ {
>+ auto const __pred = [this]
>+ {
>+ auto __old = __atomic_impl::load(&this->_M_a,
>+ memory_order::acquire);
>+ if (__old == 0)
>+ return false;
>+ return __atomic_impl::compare_exchange_strong(&this->_M_a,
>+ __old, __old - 1,
>+ memory_order::acquire,
>+ memory_order::release);
>+ };
>+
>+ auto __old = __atomic_impl::load(&_M_a, memory_order_relaxed);
>+ return __atomic_wait_for(&_M_a, __old, __pred, __rtime);
>+ }
>+
>+ _GLIBCXX_ALWAYS_INLINE void
>+ release(ptrdiff_t __update) noexcept
>+ {
>+ if (0 < __atomic_impl::fetch_add(&_M_a, __update, memory_order_release))
>+ return;
>+ if (__update > 1)
>+ __atomic_impl::notify_all(&_M_a);
>+ else
>+ __atomic_impl::notify_one(&_M_a);
>+ }
>+
>+ private:
>+ alignas(__alignof__(_Tp)) _Tp _M_a;
>+ };
>+
>+#ifdef _GLIBCXX_REQUIRE_POSIX_SEMAPHORE
What is this case for? This macro seems to only exist for use by a
single testcase.
Is it supposed to be something users can set? If so, it needs to be
documented as ABI-breaking and as implying that counting_semaphore
cannot be use with counts higher than SEM_VALUE_MAX.
>+ template<ptrdiff_t __least_max_value>
>+ using __semaphore_base = __platform_semaphore<__least_max_value>;
>+#else
>+# ifdef _GLIBCXX_HAVE_LINUX_FUTEX
>+ template<ptrdiff_t __least_max_value>
>+ using __semaphore_base = conditional_t<(
>+ __least_max_value >= 0
This condition is redundant, we already know that counting_semaphore
has checked the value is non-negative.
>+ && __least_max_value <= __detail::__platform_wait_max_value),
>+ __atomic_semaphore<__detail::__platform_wait_t>,
>+ __atomic_semaphore<ptrdiff_t>>;
>+
>+// __platform_semaphore
>+# elif defined _GLIBCXX_HAVE_POSIX_SEMAPHORE
>+ template<ptrdiff_t __least_max_value>
>+ using __semaphore_base = conditional_t<(
>+ __least_max_value >= 0
Redundant condition again.
>+ && __least_max_value <= SEM_VALUE_MAX),
>+ __platform_semaphore<__least_max_value>,
>+ __atomic_semaphore<ptrdiff_t>>;
>+# else
>+ template<ptrdiff_t __least_max_value>
>+ using __semaphore_base = __atomic_semaphore<ptrdiff_t>;
>+# endif
>+#endif
>+
>+_GLIBCXX_END_NAMESPACE_VERSION
>+} // namespace std
>+
>+#endif
>diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic
>index a455286a784..3f18774031d 100644
>--- a/libstdc++-v3/include/std/atomic
>+++ b/libstdc++-v3/include/std/atomic
>@@ -163,6 +163,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> compare_exchange_strong(bool& __i1, bool __i2,
> memory_order __m = memory_order_seq_cst) volatile noexcept
> { return _M_base.compare_exchange_strong(__i1, __i2, __m); }
>+
>+#if __cplusplus > 201703L
>+ void wait(bool __old, memory_order __m = memory_order_seq_cst) const noexcept
>+ { _M_base.wait(__old, __m); }
>+
>+ // TODO add const volatile overload
>+
>+ void notify_one() const noexcept
>+ { _M_base.notify_one(); }
>+
>+ void notify_all() const noexcept
>+ { _M_base.notify_all(); }
>+#endif
> };
>
> #if __cplusplus <= 201703L
>@@ -352,6 +365,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> memory_order __m = memory_order_seq_cst) volatile noexcept
> { return compare_exchange_strong(__e, __i, __m,
> __cmpexch_failure_order(__m)); }
>+#if __cplusplus > 201703L
>+ void wait(_Tp __old, memory_order __m = memory_order_seq_cst) noexcept
>+ { _M_i.wait(__old, __m); }
This can't be right. _M_i is of type _Tp in std::atomic<_Tp>, it doesn't
have a wait member function.
If this compiles it suggests there are no tests for these members on
the primary template, e.g. something like:
void
test01()
{
struct S { int i; };
std:::atomic<S> s;
s.wait();
}
>+
>+ // TODO add const volatile overload
>+
>+ void notify_one() const noexcept
>+ { _M_i.notify_one(); }
>+
>+ void notify_all() const noexcept
>+ { _M_i.notify_all(); }
>+#endif
>+
> };
> #undef _GLIBCXX20_INIT
>
>@@ -590,6 +616,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> __cmpexch_failure_order(__m));
> }
>
>+#if __cplusplus > 201703L
>+ void wait(__pointer_type __old, memory_order __m = memory_order_seq_cst) noexcept
>+ { _M_b.wait(__old, __m); }
>+
>+ // TODO add const volatile overload
>+
>+ void notify_one() const noexcept
>+ { _M_b.notify_one(); }
>+
>+ void notify_all() const noexcept
>+ { _M_b.notify_all(); }
>+#endif
> __pointer_type
> fetch_add(ptrdiff_t __d,
> memory_order __m = memory_order_seq_cst) noexcept
>@@ -1342,6 +1380,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> memory_order_seq_cst);
> }
>
>+
>+#if __cplusplus > 201703L
>+ template<typename _Tp>
>+ inline void atomic_wait(const atomic<_Tp>* __a,
Newline after the return type.
>+ typename std::atomic<_Tp>::value_type __old) noexcept
>+ { __a->wait(__old); }
>+
>+ template<typename _Tp>
>+ inline void atomic_wait_explicit(const atomic<_Tp>* __a,
And here.
>+ typename std::atomic<_Tp>::value_type __old,
>+ std::memory_order __m) noexcept
>+ { __a->wait(__old, __m); }
>+
>+ template<typename _Tp>
>+ inline void atomic_notify_one(atomic<_Tp>* __a) noexcept
>+ { __a->notify_one(); }
>+
>+ template<typename _Tp>
>+ inline void atomic_notify_all(atomic<_Tp>* __a) noexcept
>+ { __a->notify_all(); }
>+
>+#endif // C++2a
>+
> // Function templates for atomic_integral and atomic_pointer operations only.
> // Some operations (and, or, xor) are only available for atomic integrals,
> // which is implemented by taking a parameter of type __atomic_base<_ITp>*.
>diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch
>new file mode 100644
>index 00000000000..aa5299d9fdd
>--- /dev/null
>+++ b/libstdc++-v3/include/std/latch
>@@ -0,0 +1,90 @@
>+// <latch> -*- C++ -*-
>+
>+// 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.
>+
>+// Under Section 7 of GPL version 3, you are granted additional
>+// permissions described in the GCC Runtime Library Exception, version
>+// 3.1, as published by the Free Software Foundation.
>+
>+// You should have received a copy of the GNU General Public License and
>+// a copy of the GCC Runtime Library Exception along with this program;
>+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
>+// <http://www.gnu.org/licenses/>.
>+
>+/** @file include/latch
>+ * This is a Standard C++ Library header.
>+ */
>+
>+#ifndef _GLIBCXX_LATCH
>+#define _GLIBCXX_LATCH
>+
>+#pragma GCC system_header
>+
>+#if __cplusplus > 201703L
>+#define __cpp_lib_latch 201907L
>+
>+#include <bits/atomic_base.h>
>+#include <ext/numeric_traits.h>
>+
>+namespace std _GLIBCXX_VISIBILITY(default)
>+{
>+_GLIBCXX_BEGIN_NAMESPACE_VERSION
>+
>+ class latch
>+ {
>+ public:
>+ static constexpr
>+ _GLIBCXX_ALWAYS_INLINE ptrdiff_t
I don't think we need _GLIBCXX_ALWAYS_INLINE here.
>+ max() noexcept
>+ { return __gnu_cxx::__numeric_traits<ptrdiff_t>::__max; }
>+
>+ constexpr explicit latch(ptrdiff_t __expected) : _M_a(__expected) { }
Add noexcept.
>+
>+ ~latch() = default;
>+ latch(const latch&) = delete;
>+ latch& operator=(const latch&) = delete;
>+
>+ _GLIBCXX_ALWAYS_INLINE void
>+ count_down(ptrdiff_t __update = 1)
>+ {
>+ auto const __old = __atomic_impl::fetch_sub(&_M_a, __update, memory_order::release);
It looks like this could use atomic_ref too, although there'd be less
benefit here.
>+ if (__old == __update)
>+ __atomic_impl::notify_all(&_M_a);
>+ }
>+
>+ _GLIBCXX_ALWAYS_INLINE bool
>+ try_wait() const noexcept
>+ { return __atomic_impl::load(&_M_a, memory_order::acquire) == 0; }
>+
>+ _GLIBCXX_ALWAYS_INLINE void
>+ wait() const
>+ {
>+ auto const __old = __atomic_impl::load(&_M_a, memory_order::acquire);
>+ __atomic_wait(&_M_a, __old, [this] { return this->try_wait(); });
>+ }
>+
>+ _GLIBCXX_ALWAYS_INLINE void
>+ arrive_and_wait(ptrdiff_t __update = 1)
>+ {
>+ count_down();
>+ wait();
>+ }
>+
>+ private:
>+ alignas(__alignof__(ptrdiff_t)) ptrdiff_t _M_a;
>+ };
>+_GLIBCXX_END_NAMESPACE_VERSION
>+} // namespace
>+#endif // __cplusplus > 201703L
>+#endif // _GLIBCXX_LATCH
>diff --git a/libstdc++-v3/include/std/semaphore b/libstdc++-v3/include/std/semaphore
>new file mode 100644
>index 00000000000..90cf3244647
>--- /dev/null
>+++ b/libstdc++-v3/include/std/semaphore
>@@ -0,0 +1,86 @@
>+// <semaphore> -*- C++ -*-
>+
>+// 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.
>+
>+// Under Section 7 of GPL version 3, you are granted additional
>+// permissions described in the GCC Runtime Library Exception, version
>+// 3.1, as published by the Free Software Foundation.
>+
>+// You should have received a copy of the GNU General Public License and
>+// a copy of the GCC Runtime Library Exception along with this program;
>+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
>+// <http://www.gnu.org/licenses/>.
>+
>+/** @file include/semaphore
>+ * This is a Standard C++ Library header.
>+ */
>+
>+#ifndef _GLIBCXX_SEMAPHORE
>+#define _GLIBCXX_SEMAPHORE
>+
>+#pragma GCC system_header
>+
>+#if __cplusplus > 201703L
>+#define __cpp_lib_semaphore 201907L
>+#include <bits/semaphore_base.h>
>+#include <ext/numeric_traits.h>
>+
>+namespace std _GLIBCXX_VISIBILITY(default)
>+{
>+_GLIBCXX_BEGIN_NAMESPACE_VERSION
>+
>+ template<ptrdiff_t __least_max_value =
>+ __gnu_cxx::__numeric_traits<ptrdiff_t>::__max>
>+ class counting_semaphore
>+ {
>+ static_assert(__least_max_value >=0, "");
Add a space before the 0. Get rid of the empty string literal.
>+
>+ __semaphore_base<__least_max_value> _M_sem;
"base" seems a bit misleading here when it's a member not a base
class. Would __semaphore_impl be better?
>+
>+ public:
>+ explicit counting_semaphore(ptrdiff_t __desired) noexcept
>+ : _M_sem(__desired)
>+ { }
>+
>+ ~counting_semaphore() = default;
>+
>+ counting_semaphore(const counting_semaphore&) = delete;
>+ counting_semaphore& operator=(const counting_semaphore&) = delete;
>+
>+ static constexpr ptrdiff_t max() noexcept
>+ { return __least_max_value; }
>+
>+ void release(ptrdiff_t __update = 1)
We can add noexcept here, since we know neither of the
__semaphore_base types will throw. If you envision alternative
implementations in future, then it would be futureproof to use
noexcept(noexcept(_M_sem.release(1)))
>+ { _M_sem.release(__update); }
>+
>+ void acquire()
Same here.
>+ { _M_sem.acquire(); }
>+
>+ bool try_acquire() noexcept
>+ { return _M_sem.try_acquire(); }
>+
>+ template<class _Rep, class _Period>
>+ bool try_acquire_for(const std::chrono::duration<_Rep, _Period>& __rel_time)
Newline after the return type (the line is too long otherwise).
This one can potentially throw because of the duration arithmetic on
_Rep objects.
>+ { return _M_sem.try_acquire_for(__rel_time); }
>+
>+ template<class _Clock, class _Duration>
>+ bool try_acquire_until(const std::chrono::time_point<_Clock, _Duration>& __abs_time)
Newline after the return type (I think it's still going to be too
long).
>+ { return _M_sem.try_acquire_until(__abs_time); }
>+ };
>+
>+ using binary_semaphore = std::counting_semaphore<1>;
>+_GLIBCXX_END_NAMESPACE_VERSION
>+} // namespace
>+#endif // __cplusplus > 201703L
>+#endif // _GLIBCXX_SEMAPHORE
>diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
>index c6bde2cfbda..f09da3344f7 100644
>--- a/libstdc++-v3/include/std/version
>+++ b/libstdc++-v3/include/std/version
>@@ -189,6 +189,8 @@
> #endif
> #define __cpp_lib_type_identity 201806L
> #define __cpp_lib_unwrap_ref 201811L
>+#define __cpp_lib_semaphore 201907L
>+#define __cpp_lib_latch 201907L
You're adding these macros in the freestanding section, and these
aren't freestanding headers. They need to be in the _GLIBCXX_HOSTED
block, and the macros need to be in alphabetical order.
> #if _GLIBCXX_HOSTED
> #undef __cpp_lib_array_constexpr
>diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/atomic_refs.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/atomic_refs.cc
>new file mode 100644
>index 00000000000..1ced9d44b20
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/atomic_refs.cc
>@@ -0,0 +1,103 @@
>+// { dg-options "-std=gnu++2a -pthread -latomic -L../../libatomic/.libs" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { 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 <atomic>
>+#include <thread>
>+#include <mutex>
>+#include <condition_variable>
>+#include <chrono>
>+#include <type_traits>
>+
>+#include <testsuite_hooks.h>
>+
>+template<typename Tp>
>+Tp check_wait_notify(Tp val1, Tp val2)
>+{
>+ using namespace std::literals::chrono_literals;
>+
>+ std::mutex m;
>+ std::condition_variable cv;
>+
>+ Tp aa = val1;
>+ std::atomic_ref<Tp> a(aa);
>+ std::thread t([&]
>+ {
>+ cv.notify_one();
>+ a.wait(val1);
>+ if (a.load() != val2)
>+ a = val1;
>+ });
>+ std::unique_lock<std::mutex> l(m);
>+ cv.wait(l);
>+ std::this_thread::sleep_for(100ms);
>+ a.store(val2);
>+ a.notify_one();
>+ t.join();
>+ return a.load();
>+}
>+
>+template<typename Tp,
>+ bool = std::is_integral_v<Tp>
>+ || std::is_floating_point_v<Tp>>
>+struct check;
>+
>+template<typename Tp>
>+struct check<Tp, true>
>+{
>+ check()
>+ {
>+ Tp a = 0;
>+ Tp b = 42;
>+ VERIFY(check_wait_notify(a, b) == b);
>+ }
>+};
>+
>+template<typename Tp>
>+struct check<Tp, false>
>+{
>+ check(Tp b)
>+ {
>+ Tp a;
>+ VERIFY(check_wait_notify(a, b) == b);
>+ }
>+};
>+
>+struct foo
>+{
>+ long a = 0;
>+ long b = 0;
>+
>+ foo& operator=(foo const&) = default;
>+
>+ friend bool
>+ operator==(foo const& rhs, foo const& lhs)
>+ { return rhs.a == lhs.a && rhs.b == lhs.b; }
>+};
>+
>+int
>+main ()
>+{
>+ check<long>();
>+ check<double>();
>+ check<foo>({42, 48});
>+ return 0;
>+}
>diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
>new file mode 100644
>index 00000000000..b9fc063c66f
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
>@@ -0,0 +1,59 @@
>+// { dg-options "-std=gnu++2a -pthread" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { 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 <atomic>
>+#include <thread>
>+#include <mutex>
>+#include <condition_variable>
>+#include <type_traits>
>+#include <chrono>
>+
>+#include <testsuite_hooks.h>
>+
>+int
>+main ()
>+{
>+ using namespace std::literals::chrono_literals;
>+
>+ std::mutex m;
>+ std::condition_variable cv;
>+
>+ std::atomic<bool> a(false);
>+ std::atomic<bool> b(false);
>+ std::thread t([&]
>+ {
>+ cv.notify_one();
>+ a.wait(false);
>+ if (a.load())
>+ {
>+ b.store(true);
>+ }
>+ });
>+ std::unique_lock<std::mutex> l(m);
>+ cv.wait(l);
>+ std::this_thread::sleep_for(100ms);
>+ a.store(true);
>+ a.notify_one();
>+ t.join();
>+ VERIFY( b.load() );
>+ return 0;
>+}
>diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/floats.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/floats.cc
>new file mode 100644
>index 00000000000..1d032085752
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/floats.cc
>@@ -0,0 +1,32 @@
>+// { dg-options "-std=gnu++2a -pthread -latomic -L../../libatomic/.libs" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { 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 "generic.h"
>+
>+int
>+main ()
>+{
>+ check<float> f;
>+ check<double> d;
>+ check<long double> l;
>+ return 0;
>+}
>diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.h b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.h
>new file mode 100644
>index 00000000000..0da374ece87
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.h
>@@ -0,0 +1,88 @@
>+// -*- C++ -*- header.
This isn't a header. I don't think this modeline should be here.
The test seems to be missing any dg-options, target selectors etc.
>+// 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 <atomic>
>+#include <thread>
>+#include <mutex>
>+#include <condition_variable>
>+#include <chrono>
>+
>+#include <testsuite_hooks.h>
>+
>+template<typename Tp>
>+Tp check_wait_notify(Tp val1, Tp val2)
>+{
>+ using namespace std::literals::chrono_literals;
>+
>+ std::mutex m;
>+ std::condition_variable cv;
>+
>+ std::atomic<Tp> a(val1);
>+ std::thread t([&]
>+ {
>+ cv.notify_one();
>+ a.wait(val1);
>+ if (a.load() != val2)
>+ a = val1;
>+ });
>+ std::unique_lock<std::mutex> l(m);
>+ cv.wait(l);
>+ std::this_thread::sleep_for(100ms);
>+ a.store(val2);
>+ a.notify_one();
>+ t.join();
>+ return a.load();
>+}
>+
>+template<typename Tp>
>+Tp check_atomic_wait_notify(Tp val1, Tp val2)
>+{
>+ using namespace std::literals::chrono_literals;
>+
>+ std::mutex m;
>+ std::condition_variable cv;
>+
>+ std::atomic<Tp> a(val1);
>+ std::thread t([&]
>+ {
>+ cv.notify_one();
>+ std::atomic_wait(&a, val1);
>+ if (a.load() != val2)
>+ a = val1;
>+ });
>+ std::unique_lock<std::mutex> l(m);
>+ cv.wait(l);
>+ std::this_thread::sleep_for(100ms);
>+ a.store(val2);
>+ std::atomic_notify_one(&a);
>+ t.join();
>+ return a.load();
>+}
>+
>+template<typename Tp>
>+struct check
>+{
>+ check()
>+ {
>+ Tp a = 0;
>+ Tp b = 42;
>+ VERIFY(check_wait_notify(a, b) == b);
>+ VERIFY(check_atomic_wait_notify(a, b) == b);
>+ }
>+};
>diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/integrals.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/integrals.cc
>new file mode 100644
>index 00000000000..2afd19a7d14
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/integrals.cc
>@@ -0,0 +1,56 @@
>+// { dg-options "-std=gnu++2a -pthread" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { 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 "generic.h"
>+
>+int
>+main ()
>+{
>+ // check<bool> bb;
>+ check<char> ch;
>+ check<signed char> sch;
>+ check<unsigned char> uch;
>+ check<short> s;
>+ check<unsigned short> us;
>+ check<int> i;
>+ check<unsigned int> ui;
>+ check<long> l;
>+ check<unsigned long> ul;
>+ check<long long> ll;
>+ check<unsigned long long> ull;
>+
>+ check<wchar_t> wch;
>+ check<char8_t> ch8;
>+ check<char16_t> ch16;
>+ check<char32_t> ch32;
>+
>+ check<int8_t> i8;
>+ check<int16_t> i16;
>+ check<int32_t> i32;
>+ check<int64_t> i64;
>+
>+ check<uint8_t> u8;
>+ check<uint16_t> u16;
>+ check<uint32_t> u32;
>+ check<uint64_t> u64;
>+ return 0;
>+}
>diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
>new file mode 100644
>index 00000000000..8531bb2e788
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
>@@ -0,0 +1,59 @@
>+// { dg-options "-std=gnu++2a -pthread" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { 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 <atomic>
>+#include <thread>
>+#include <mutex>
>+#include <condition_variable>
>+#include <type_traits>
>+#include <chrono>
>+
>+#include <testsuite_hooks.h>
>+
>+int
>+main ()
>+{
>+ using namespace std::literals::chrono_literals;
>+
>+ std::mutex m;
>+ std::condition_variable cv;
>+
>+ long aa;
>+ long bb;
>+
>+ std::atomic<long*> a(nullptr);
>+ std::thread t([&]
>+ {
>+ cv.notify_one();
>+ a.wait(nullptr);
>+ if (a.load() == &aa)
>+ a.store(&bb);
>+ });
>+ std::unique_lock<std::mutex> l(m);
>+ cv.wait(l);
>+ std::this_thread::sleep_for(100ms);
>+ a.store(&aa);
>+ a.notify_one();
>+ t.join();
>+ VERIFY( a.load() == &bb);
>+ return 0;
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/latch/1.cc b/libstdc++-v3/testsuite/30_threads/latch/1.cc
>new file mode 100644
>index 00000000000..aa203cdf525
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/latch/1.cc
>@@ -0,0 +1,27 @@
>+// 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 <latch>
>+
>+#ifndef __cpp_lib_latch
>+# error "Feature-test macro for latch missing in <latch>"
>+#elif __cpp_lib_latch!= 201907L
>+# error "Feature-test macro for latch has wrong value in <latch>"
>+#endif
>diff --git a/libstdc++-v3/testsuite/30_threads/latch/2.cc b/libstdc++-v3/testsuite/30_threads/latch/2.cc
>new file mode 100644
>index 00000000000..756727f33b3
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/latch/2.cc
>@@ -0,0 +1,27 @@
>+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
Just 2020.
>+//
>+// 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 <version>
>+
>+#ifndef __cpp_lib_latch
>+# error "Feature-test macro for latch missing in <version>"
>+#elif __cpp_lib_latch != 201907L
>+# error "Feature-test macro for latch has wrong value in <version>"
>+#endif
>diff --git a/libstdc++-v3/testsuite/30_threads/latch/3.cc b/libstdc++-v3/testsuite/30_threads/latch/3.cc
>new file mode 100644
>index 00000000000..10bb500d261
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/latch/3.cc
>@@ -0,0 +1,50 @@
>+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
>+//
Just 2020.
>+// 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 -pthread" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { dg-require-gthreads "" }
>+//
>+#include <latch>
>+#include <atomic>
>+#include <thread>
>+#include <testsuite_hooks.h>
>+
>+int main()
>+{
>+ std::atomic<int> a(0);
>+
>+ std::latch l(3);
>+
>+ VERIFY( !l.try_wait() );
>+
>+ auto fn = [&]
>+ {
>+ ++a;
>+ l.count_down();
>+ };
>+
>+ std::thread t0(fn);
>+ std::thread t1(fn);
>+
>+ l.arrive_and_wait();
>+ t0.join();
>+ t1.join();
>+
>+ VERIFY( l.try_wait() );
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/1.cc b/libstdc++-v3/testsuite/30_threads/semaphore/1.cc
>new file mode 100644
>index 00000000000..1bbca687fc3
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/semaphore/1.cc
>@@ -0,0 +1,27 @@
>+// 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 <semaphore>
>+
>+#ifndef __cpp_lib_semaphore
>+# error "Feature-test macro for semaphore missing in <semaphore>"
>+#elif __cpp_lib_semaphore != 201907L
>+# error "Feature-test macro for semaphore has wrong value in <semaphore>"
>+#endif
>diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/2.cc b/libstdc++-v3/testsuite/30_threads/semaphore/2.cc
>new file mode 100644
>index 00000000000..b96b8a59c64
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/semaphore/2.cc
>@@ -0,0 +1,27 @@
>+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
Just 2020.
>+//
>+// 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 <version>
>+
>+#ifndef __cpp_lib_semaphore
>+# error "Feature-test macro for semaphore missing in <version>"
>+#elif __cpp_lib_semaphore != 201907L
>+# error "Feature-test macro for semaphore has wrong value in <version>"
>+#endif
>diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value_neg.cc b/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value_neg.cc
>new file mode 100644
>index 00000000000..1ac9d261ca5
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value_neg.cc
>@@ -0,0 +1,28 @@
>+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
Just 2020.
>+//
>+// 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 <semaphore>
>+
>+int main()
>+{
>+ std::counting_semaphore<-1> sem(2);
>+ return 0;
>+}
>+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
>diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire.cc
>new file mode 100644
>index 00000000000..d38cef86cfc
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire.cc
>@@ -0,0 +1,55 @@
>+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
Just 2020.
>+//
>+// 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 -pthread" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { dg-require-gthreads "" }
>+
>+#include <semaphore>
>+#include <limits>
>+#include <cstddef>
>+#include <testsuite_hooks.h>
>+
>+void test01()
>+{
>+ std::counting_semaphore<10> s(3);
>+
>+ s.acquire();
>+ VERIFY( s.try_acquire() );
>+ VERIFY( s.try_acquire() );
>+ VERIFY( !s.try_acquire() );
>+ s.release();
>+ VERIFY( s.try_acquire() );
>+}
>+
>+void test02()
>+{
>+ std::binary_semaphore s(1);
>+
>+ s.acquire();
>+ VERIFY( !s.try_acquire() );
>+ s.release();
>+ VERIFY( s.try_acquire() );
>+}
>+
>+
>+int main()
>+{
>+ test01();
>+ test02();
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc
>new file mode 100644
>index 00000000000..965554a3c28
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc
>@@ -0,0 +1,85 @@
>+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
Just 2020.
>+//
>+// 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 -pthread" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { dg-require-gthreads "" }
>+
>+#include <semaphore>
>+#include <chrono>
>+#include <thread>
>+#include <atomic>
>+#include <testsuite_hooks.h>
>+
>+void test01()
>+{
>+ using namespace std::chrono_literals;
>+ std::counting_semaphore<10> s(2);
>+ s.acquire();
>+
>+ auto const dur = 250ms;
>+ {
>+ auto const t0 = std::chrono::steady_clock::now();
>+ VERIFY( s.try_acquire_for(dur) );
>+ auto const diff = std::chrono::steady_clock::now() - t0;
>+ VERIFY( diff < dur );
>+ }
>+
>+ {
>+ auto const t0 = std::chrono::steady_clock::now();
>+ VERIFY( !s.try_acquire_for(dur) );
>+ auto const diff = std::chrono::steady_clock::now() - t0;
>+ VERIFY( diff >= dur );
>+ }
>+}
>+
>+void test02()
>+{
>+ using namespace std::chrono_literals;
>+ std::binary_semaphore s(1);
>+ std::atomic<int> a(0), b(0);
>+ std::thread t([&] {
>+ a.wait(0);
>+ auto const dur = 250ms;
>+ VERIFY( !s.try_acquire_for(dur) );
>+ b++;
>+ b.notify_one();
>+
>+ a.wait(1);
>+ VERIFY( s.try_acquire_for(dur) );
>+ b++;
>+ b.notify_one();
>+ });
>+ t.detach();
>+
>+ s.acquire();
>+ a++;
>+ a.notify_one();
>+ b.wait(0);
>+ s.release();
>+ a++;
>+ a.notify_one();
>+
>+ b.wait(1);
>+}
>+
>+int main()
>+{
>+ test01();
>+ test02();
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_futex.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_futex.cc
>new file mode 100644
>index 00000000000..5e05606e97f
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_futex.cc
>@@ -0,0 +1,51 @@
>+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
Just 2020.
>+//
>+// 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 -pthread" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { dg-require-gthreads "" }
>+
>+#include <semaphore>
>+#include <limits>
>+#include <cstddef>
>+#include <testsuite_hooks.h>
>+
>+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
>+void test01()
>+{
>+ // the implementation optimizes for values of least_max_t that can fit
>+ // in a futex, make sure we cover the case where least_max_t doesn't
>+ auto constexpr least_max_t = std::numeric_limits<std::ptrdiff_t>::max();
>+ std::counting_semaphore<least_max_t> s(3);
>+
>+ s.acquire();
>+ VERIFY( s.try_acquire() );
>+ VERIFY( s.try_acquire() );
>+ VERIFY( !s.try_acquire() );
>+ s.release();
>+ VERIFY( s.try_acquire() );
>+}
>+
>+#endif
>+
>+int main()
>+{
>+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
>+ test01();
>+#endif
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc
>new file mode 100644
>index 00000000000..bf99fd3cf8f
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc
>@@ -0,0 +1,169 @@
>+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
Just 2020.
>+//
>+// 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 -pthread" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { dg-require-gthreads "" }
>+
>+#include <semaphore>
>+#include <chrono>
>+#include <thread>
>+#include <atomic>
>+#include <testsuite_hooks.h>
>+
>+#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
>+ // The implementation supports posix as an implementation strategy
>+ // make sure we cover that case
>+#define _GLIBCXX_REQUIRE_POSIX_SEMAPHORE
This macro is defined too late to do anything. It would ned to be
defined before including <semaphore> to have any effect.
>+void test01()
>+{
>+ std::counting_semaphore<10> s(3);
>+
>+ s.acquire();
>+ VERIFY( s.try_acquire() );
>+ VERIFY( s.try_acquire() );
>+ VERIFY( !s.try_acquire() );
>+ s.release();
>+ VERIFY( s.try_acquire() );
>+}
>+
>+void test02()
>+{
>+ using namespace std::chrono_literals;
>+ std::counting_semaphore<10> s(2);
>+ s.acquire();
>+
>+ auto const dur = 250ms;
>+ {
>+ auto const t0 = std::chrono::steady_clock::now();
>+ VERIFY( s.try_acquire_for(dur) );
>+ auto const diff = std::chrono::steady_clock::now() - t0;
>+ VERIFY( diff < dur );
>+ }
>+
>+ {
>+ auto const t0 = std::chrono::steady_clock::now();
>+ VERIFY( !s.try_acquire_for(dur) );
>+ auto const diff = std::chrono::steady_clock::now() - t0;
>+ VERIFY( diff >= dur );
>+ }
>+}
>+
>+void test03()
>+{
>+ using namespace std::chrono_literals;
>+ std::binary_semaphore s(1);
>+ std::atomic<int> a(0), b(0);
>+ std::thread t([&] {
>+ a.wait(0);
>+ auto const dur = 250ms;
>+ VERIFY( !s.try_acquire_for(dur) );
>+ b++;
>+ b.notify_one();
>+
>+ a.wait(1);
>+ VERIFY( s.try_acquire_for(dur) );
>+ b++;
>+ b.notify_one();
>+ });
>+ t.detach();
>+
>+ s.acquire();
>+ a++;
>+ a.notify_one();
>+ b.wait(0);
>+ s.release();
>+ a++;
>+ a.notify_one();
>+
>+ b.wait(1);
>+}
>+
>+void test04()
>+{
>+ using namespace std::chrono_literals;
>+ std::counting_semaphore<10> s(2);
>+ s.acquire();
>+
>+ auto const dur = 250ms;
>+ {
>+ auto const at = std::chrono::system_clock::now() + dur;
>+ auto const t0 = std::chrono::steady_clock::now();
>+ VERIFY( s.try_acquire_until(at) );
>+ auto const diff = std::chrono::steady_clock::now() - t0;
>+ VERIFY( diff < dur );
>+ }
>+
>+ {
>+ auto const at = std::chrono::system_clock::now() + dur;
>+ auto const t0 = std::chrono::steady_clock::now();
>+ VERIFY( !s.try_acquire_until(at) );
>+ auto const diff = std::chrono::steady_clock::now() - t0;
>+ VERIFY( diff >= dur );
>+ }
>+}
>+
>+void test05()
>+{
>+ using namespace std::chrono_literals;
>+ std::binary_semaphore s(1);
>+ std::atomic<int> a(0), b(0);
>+ std::thread t([&] {
>+ a.wait(0);
>+ auto const dur = 250ms;
>+ {
>+ auto const at = std::chrono::system_clock::now() + dur;
>+ VERIFY( !s.try_acquire_until(at) );
>+
>+ b++;
>+ b.notify_one();
>+ }
>+
>+ a.wait(1);
>+ {
>+ auto const at = std::chrono::system_clock::now() + dur;
>+ VERIFY( s.try_acquire_until(at) );
>+ }
>+ b++;
>+ b.notify_one();
>+ });
>+ t.detach();
>+
>+ s.acquire();
>+ a++;
>+ a.notify_one();
>+ b.wait(0);
>+ s.release();
>+ a++;
>+ a.notify_one();
>+
>+ b.wait(1);
>+}
>+#endif
>+
>+int main()
>+{
>+#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
>+ test01();
>+ test02();
>+ test03();
>+ test04();
>+ test05();
>+#endif
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
>new file mode 100644
>index 00000000000..cc67c5c0bf0
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
>@@ -0,0 +1,94 @@
>+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
Just 2020.
>+//
>+// 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 -pthread" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-effective-target pthread }
>+// { dg-require-gthreads "" }
>+
>+#include <semaphore>
>+#include <chrono>
>+#include <thread>
>+#include <atomic>
>+#include <testsuite_hooks.h>
>+
>+void test01()
>+{
>+ using namespace std::chrono_literals;
>+ std::counting_semaphore<10> s(2);
>+ s.acquire();
>+
>+ auto const dur = 250ms;
>+ {
>+ auto const at = std::chrono::system_clock::now() + dur;
>+ auto const t0 = std::chrono::steady_clock::now();
>+ VERIFY( s.try_acquire_until(at) );
>+ auto const diff = std::chrono::steady_clock::now() - t0;
>+ VERIFY( diff < dur );
>+ }
>+
>+ {
>+ auto const at = std::chrono::system_clock::now() + dur;
>+ auto const t0 = std::chrono::steady_clock::now();
>+ VERIFY( !s.try_acquire_until(at) );
>+ auto const diff = std::chrono::steady_clock::now() - t0;
>+ VERIFY( diff >= dur );
>+ }
>+}
>+
>+void test02()
>+{
>+ using namespace std::chrono_literals;
>+ std::binary_semaphore s(1);
>+ std::atomic<int> a(0), b(0);
>+ std::thread t([&] {
>+ a.wait(0);
>+ auto const dur = 250ms;
>+ {
>+ auto const at = std::chrono::system_clock::now() + dur;
>+ VERIFY( !s.try_acquire_until(at) );
>+
>+ b++;
>+ b.notify_one();
>+ }
>+
>+ a.wait(1);
>+ {
>+ auto const at = std::chrono::system_clock::now() + dur;
>+ VERIFY( s.try_acquire_until(at) );
>+ }
>+ b++;
>+ b.notify_one();
>+ });
>+ t.detach();
>+
>+ s.acquire();
>+ a++;
>+ a.notify_one();
>+ b.wait(0);
>+ s.release();
>+ a++;
>+ a.notify_one();
>+
>+ b.wait(1);
>+}
>+
>+int main()
>+{
>+ test01();
>+ test02();
>+}
>--
>2.26.2
>
More information about the Gcc-patches
mailing list