[PATCH] libstdc++: Add support for C++20 barriers

Jonathan Wakely jwakely@redhat.com
Fri Dec 18 10:08:55 GMT 2020


On 17/12/20 15:37 -0800, Thomas Rodgers wrote:
>From: Thomas Rodgers <trodgers@redhat.com>
>
>Cleans up a few things mentioned on IRC.
>
>Adds <barrier>
>
>libstdc++/ChangeLog:
>
>	* doc/doxygen/user.cfg.in: Add new header.
>	* include/Makefile.am (std_headers): likewise.
>	* include/Makefile.in: Regenerate.
>        * include/precompiled/stdc++.h: Add new header.
>	* include/std/barrier: New file.
>	* include/std/version: Add __cpp_lib_barrier feature test macro.
>	* testsuite/30_thread/barrier/1.cc: New test.
>	* testsuite/30_thread/barrier/2.cc: Likewise.
>	* testsuite/30_thread/barrier/arrive_and_drop.cc: Likewise.
>	* testsuite/30_thread/barrier/arrive_and_wait.cc: Likewise.
>	* testsuite/30_thread/barrier/arrive.cc: Likewise.
>	* testsuite/30_thread/barrier/completion.cc: Likewise.
>	* testsuite/30_thread/barrier/max.cc: Likewise.


>+#ifndef _GLIBCXX_BARRIER
>+#define _GLIBCXX_BARRIER 1
>+
>+#pragma GCC system_header
>+
>+#if __cplusplus > 201703L
>+#include <bits/atomic_base.h>
>+#if __cpp_lib_atomic_wait  && __cpp_aligned_new

There's an extra space here before the && operator.

>+#endif // __cpp_lib_atomic_wait  && __cpp_aligned_new

And here.

>+#endif // __cplusplus > 201703L
>+#endif // _GLIBCXX_BARRIER
>+
>diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
>index e4a8bed52ab..07d17433c5b 100644
>--- a/libstdc++-v3/include/std/version
>+++ b/libstdc++-v3/include/std/version
>@@ -200,6 +200,9 @@
> #if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX
> # define __cpp_lib_atomic_wait 201907L
> #endif
>+#if __cpp_lib_atomic_wait

This needs to match the condition used in <barrier>.

>+#define __cpp_lib_barrier 201907L
>+#endif

You could just put it inside the previous block where
__cpp_lib_atomic_wait is defined:

#if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX
# define __cpp_lib_atomic_wait 201907L
# if __cpp_aligned_new
#  define __cpp_lib_barrier 201907L
# endif
#endif

> #define __cpp_lib_bind_front 201907L
> #if __has_builtin(__builtin_bit_cast)
> # define __cpp_lib_bit_cast 201806L
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/1.cc b/libstdc++-v3/testsuite/30_threads/barrier/1.cc
>new file mode 100644
>index 00000000000..0b38160a58b
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/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 } }

This test will fail for non-gthreads targets, because they don't
define the macro. This needs the same condition as the similar
29_atomics/atomic/wait_notify/1.cc test:

// { dg-require-effective-target gthreads }

(which is the new way to say { dg-requires-gthread "" })

>+#include <barrier>
>+
>+#ifndef __cpp_lib_barrier
>+# error "Feature-test macro for barrier missing in <barrier>"
>+#elif __cpp_lib_barrier != 201907L
>+# error "Feature-test macro for barrier has wrong value in <barrier>"
>+#endif
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/2.cc b/libstdc++-v3/testsuite/30_threads/barrier/2.cc
>new file mode 100644
>index 00000000000..1d8d83639e0
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/2.cc
>@@ -0,0 +1,27 @@
>+// Copyright (C) 2019-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 } }

Same here.

>+#include <version>
>+
>+#ifndef __cpp_lib_barrier
>+# error "Feature-test macro for barrier missing in <version>"
>+#elif __cpp_lib_barrier != 201907L
>+# error "Feature-test macro for barrier has wrong value in <version>"
>+#endif
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc
>new file mode 100644
>index 00000000000..df70587db5b
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc
>@@ -0,0 +1,48 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive.pass.cpp

Please replace "implementation" with "test" or something like that,
since this isn't the implementation. Same for all the other tests
taken from LLVM.

>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+int main(int, char**)
>+{
>+  std::barrier<> b(2);
>+
>+  auto tok = b.arrive();
>+  std::thread t([&](){
>+    (void)b.arrive();
>+  });
>+  b.wait(std::move(tok));
>+  t.join();
>+
>+  auto tok2 = b.arrive(2);
>+  b.wait(std::move(tok2));
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc
>new file mode 100644
>index 00000000000..746a8f470e3
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc
>@@ -0,0 +1,46 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive_and_drop.pass.cpp
>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+int main(int, char**)
>+{
>+  std::barrier<> b(2);
>+
>+  std::thread t([&](){
>+    b.arrive_and_drop();
>+  });
>+
>+  b.arrive_and_wait();
>+  b.arrive_and_wait();
>+  t.join();
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc
>new file mode 100644
>index 00000000000..509986f3b78
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc
>@@ -0,0 +1,46 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive_and_drop.pass.cpp

Wrong filename?

>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+int main(int, char**)
>+{
>+  std::barrier<> b(2);
>+
>+  std::thread t([&](){
>+    for(int i = 0; i < 10; ++i)
>+      b.arrive_and_wait();
>+  });
>+  for(int i = 0; i < 10; ++i)
>+    b.arrive_and_wait();
>+  t.join();
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/completion.cc b/libstdc++-v3/testsuite/30_threads/barrier/completion.cc
>new file mode 100644
>index 00000000000..c7997d9d7fb
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/completion.cc
>@@ -0,0 +1,53 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/completion.pass.cpp
>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+#include <testsuite_hooks.h>
>+
>+int main(int, char**)
>+{
>+  int x = 0;
>+  auto comp = [&] { x += 1; };
>+  std::barrier<decltype(comp)> b(2, comp);
>+
>+  std::thread t([&](){
>+      for(int i = 0; i < 10; ++i)
>+	b.arrive_and_wait();
>+  });
>+
>+  for(int i = 0; i < 10; ++i)
>+    b.arrive_and_wait();
>+
>+  VERIFY( x == 10 );
>+  t.join();
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/max.cc b/libstdc++-v3/testsuite/30_threads/barrier/max.cc
>new file mode 100644
>index 00000000000..278bc3fdd10
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/max.cc
>@@ -0,0 +1,40 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }

This should be 'compile' not 'run'.

I think I'd rather see these static_asserts put into one of the
existing tests, so we don't pay for the overhead of another dejagnu
test (with all its setup and target checking) just for this.

Maybe in barrier/1.cc since that's not doing very much work either
(and don't forget to move the dg-additional-options there too).

>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/max.pass.cpp
>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+int main(int, char**)
>+{
>+  static_assert(std::barrier<>::max() > 0, "");
>+  auto l = [](){};
>+  static_assert(std::barrier<decltype(l)>::max() > 0, "");

No need for the string literals here, this is C++20.

OK with those changes, thanks.




More information about the Libstdc++ mailing list