On 03/08/20 15:09 +0100, Jonathan Wakely wrote:
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
Why is this a template?
It means we'll instantiate identical code for counting_semaphore<3>
and counting_semaphore<4>, but they're distinct types that will bloat
the binary.
Can't we just have a single __platform_semaphore type for all max
values, and just make sure we don't instantiate it for values larger
than SEM_VALUE_MAX?
+ {
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, "");
I think it would be useful for __platform_semaphore to define a static
constexpr member like:
static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX;
And then __atomic_semaphore could define:
static constexpr _Tp _S_max = __gnu_cxx::__int_traits<_Tp>::__max;
And then the alias __semaphore_base could be defined as:
#if _GLIBCXX_HAVE_LINUX_FUTEX && ! _GLIBCXX_REQUIRE_POSIX_SEMAPHORE
// Use futex if available and user didn't force use of POSIX:
using __fast_semaphore_base = __atomic_semaphore<__platform_wait_t>;
#elif _GLIBCXX_HAVE_POSIX_SEMAPHORE
// Otherwise, use POSIX if available:
using __fast_semaphore_base = __platform_semaphore<SEM_VALUE_MAX>;
#else
// Otherwise, use atomics:
using __fast_semaphore_base = __atomic_semaphore<ptrdiff_t>;
#endif
template<ptrdiff_t __least_max_value>
using __semaphore_base = conditional_t<
__least_max_value <= __fast_semaphore_base::_S_max,
__fast_semaphore_base, __atomic_semaphore<ptrdiff_t>;
Would that make sense?
Do the comments above reflect the intent?
+#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