On Mon, 2 Nov 2020 at 19:43, Thomas Rodgers via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
>
> Testsed x86_64-pc-linux-gnu, committed to master.
>

Hi,

I can see the new tests failing on bare-metal targets using newlib
(arm-eabi, aarch64-elf):
    27_io/basic_syncbuf/1.cc (test for excess errors)
    27_io/basic_syncbuf/basic_ops/1.cc (test for excess errors)
    27_io/basic_syncbuf/requirements/types.cc (test for excess errors)
    27_io/basic_syncstream/1.cc (test for excess errors)
    27_io/basic_syncstream/basic_ops/1.cc (test for excess errors)
    27_io/basic_syncstream/requirements/types.cc (test for excess errors)

because:
libstdc++-v3/include/syncstream:142: error: 'lock_guard' does not name a type

Christophe

> Jonathan Wakely writes:
>
> > On 02/11/20 08:10 -0800, Thomas Rodgers wrote:
> >>From: Thomas Rodgers <trodg...@redhat.com>
> >>
> >>IGNORE the previous patch.
> >>
> >>Changes implementation to use a private __mutex type as discussed on
> >>IRC.
> >>
> >>libstdc++/ChangeLog:
> >>      libstdc++-v3/doc/doxygen/user.cfg.in (INPUT): Add new header.
> >>      libstdc++-v3/include/Makefile.am (std_headers): Add new header.
> >>      libstdc++-v3/include/Makefile.in: Regenerate.
> >>      libstdc++-v3/include/precompiled/stdc++.h: Include new header.
> >>      (basic_streambuf): Befriend __detail::__streambuf_core_access.
> >>      libstdc++-v3/include/std/syncstream: New header.
> >>      libstdc++-v3/include/std/version: Add __cpp_lib_syncbuf:
> >>      libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc: New test.
> >>      libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc: Likewise.
> >>      libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc:
> >>      Likewise.
> >>      libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc:
> >>      Likewise.
> >>      libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc:
> >>      Likewise.
> >>      libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc: Likewise.
> >>      libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc: Likewise.
> >>      libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc:
> >>      Likewise.
> >>      libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc:
> >>      Likewise.
> >>---
> >> libstdc++-v3/doc/doxygen/user.cfg.in          |   1 +
> >> libstdc++-v3/include/Makefile.am              |   1 +
> >> libstdc++-v3/include/Makefile.in              |   1 +
> >> libstdc++-v3/include/precompiled/stdc++.h     |   2 +-
> >> libstdc++-v3/include/std/syncstream           | 333 ++++++++++++++++++
> >> libstdc++-v3/include/std/version              |   4 +
> >> .../testsuite/27_io/basic_syncbuf/1.cc        |  28 ++
> >> .../testsuite/27_io/basic_syncbuf/2.cc        |  28 ++
> >> .../27_io/basic_syncbuf/basic_ops/1.cc        | 137 +++++++
> >> .../27_io/basic_syncbuf/requirements/types.cc |  42 +++
> >> .../27_io/basic_syncbuf/sync_ops/1.cc         | 130 +++++++
> >> .../testsuite/27_io/basic_syncstream/1.cc     |  28 ++
> >> .../testsuite/27_io/basic_syncstream/2.cc     |  28 ++
> >> .../27_io/basic_syncstream/basic_ops/1.cc     | 134 +++++++
> >> .../basic_syncstream/requirements/types.cc    |  43 +++
> >> 15 files changed, 939 insertions(+), 1 deletion(-)
> >> create mode 100644 libstdc++-v3/include/std/syncstream
> >> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc
> >> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc
> >> create mode 100644 
> >> libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc
> >> create mode 100644 
> >> libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc
> >> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc
> >> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc
> >> create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc
> >> create mode 100644 
> >> libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc
> >> create mode 100644 
> >> libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc
> >>
> >>diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in 
> >>b/libstdc++-v3/doc/doxygen/user.cfg.in
> >>index 9b49a15d31b..320f6dea688 100644
> >>--- a/libstdc++-v3/doc/doxygen/user.cfg.in
> >>+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
> >>@@ -897,6 +897,7 @@ INPUT                  = 
> >>@srcdir@/doc/doxygen/doxygroups.cc \
> >>                          include/streambuf \
> >>                          include/string \
> >>                          include/string_view \
> >>+                         include/syncstream \
> >>                          include/system_error \
> >>                          include/thread \
> >>                          include/tuple \
> >>diff --git a/libstdc++-v3/include/Makefile.am 
> >>b/libstdc++-v3/include/Makefile.am
> >>index c90ac555e15..8652b921274 100644
> >>--- a/libstdc++-v3/include/Makefile.am
> >>+++ b/libstdc++-v3/include/Makefile.am
> >>@@ -73,6 +73,7 @@ std_headers = \
> >>      ${std_srcdir}/shared_mutex \
> >>      ${std_srcdir}/span \
> >>      ${std_srcdir}/sstream \
> >>+     ${std_srcdir}/syncstream \
> >>      ${std_srcdir}/stack \
> >>      ${std_srcdir}/stdexcept \
> >>      ${std_srcdir}/stop_token \
> >>diff --git a/libstdc++-v3/include/precompiled/stdc++.h 
> >>b/libstdc++-v3/include/precompiled/stdc++.h
> >>index 7518a98c25a..8899c323a28 100644
> >>--- a/libstdc++-v3/include/precompiled/stdc++.h
> >>+++ b/libstdc++-v3/include/precompiled/stdc++.h
> >>@@ -141,6 +141,6 @@
> >> #include <ranges>
> >> #include <span>
> >> #include <stop_token>
> >>-// #include <syncstream>
> >>+#include <syncstream>
> >> #include <version>
> >> #endif
> >>diff --git a/libstdc++-v3/include/std/syncstream 
> >>b/libstdc++-v3/include/std/syncstream
> >>new file mode 100644
> >>index 00000000000..ff96ca6cf59
> >>--- /dev/null
> >>+++ b/libstdc++-v3/include/std/syncstream
> >>@@ -0,0 +1,333 @@
> >>+// <syncstream> -*- 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/syncstream
> >>+ *  This is a Standard C++ Library header.
> >>+ */
> >>+
> >>+#ifndef _GLIBCXX_SYNCSTREAM
> >>+#define _GLIBCXX_SYNCSTREAM 1
> >>+
> >>+#if __cplusplus > 201703L
> >>+
> >>+#include <bits/c++config.h>
> >>+#if _GLIBCXX_USE_CXX11_ABI
> >>+
> >>+#define __cpp_lib_syncbuf 201803L
> >>+
> >>+#pragma GCC system_header
> >>+
> >>+#include <sstream>
> >>+
> >>+#include <bits/alloc_traits.h>
> >>+#include <bits/allocator.h>
> >>+#include <bits/functexcept.h>
> >>+#include <bits/functional_hash.h>
> >>+
> >>+#if _GLIBCXX_HAS_GTHREADS
> >>+# include <bits/std_mutex.h>
> >>+#endif
> >>+
> >>+namespace std _GLIBCXX_VISIBILITY(default)
> >>+{
> >>+_GLIBCXX_BEGIN_NAMESPACE_VERSION
> >>+
> >>+  template<typename _CharT, typename _Traits = char_traits<_CharT>,
> >>+         typename _Alloc = allocator<_CharT>>
> >>+    class basic_syncbuf : public basic_streambuf<_CharT, _Traits>
> >>+    {
> >>+    public:
> >>+      using char_type = _CharT;
> >>+      using int_type = typename _Traits::int_type;
> >>+      using pos_type = typename _Traits::pos_type;
> >>+      using off_type = typename _Traits::off_type;
> >>+      using traits_type = _Traits;
> >>+      using allocator_type = _Alloc;
> >>+      using streambuf_type = basic_streambuf<_CharT, _Traits>;
> >>+
> >>+      basic_syncbuf()
> >>+      : basic_syncbuf(nullptr, allocator_type{})
> >>+      { }
> >>+
> >>+      explicit
> >>+      basic_syncbuf(streambuf_type* __obuf)
> >>+     : basic_syncbuf(__obuf, allocator_type{})
> >>+      { }
> >>+
> >>+      basic_syncbuf(streambuf_type* __obuf, const allocator_type& __alloc)
> >>+     : _M_wrapped(__obuf)
> >>+     , _M_impl(__alloc)
> >>+     , _M_mtx(__obuf)
> >>+      { }
> >>+
> >>+      basic_syncbuf(basic_syncbuf&& __other)
> >>+     : _M_wrapped(__other._M_wrapped)
> >>+     , _M_impl(std::move(__other._M_impl))
> >>+     , _M_mtx(std::move(__other._M_mtx))
> >>+     , _M_emit_on_sync(__other._M_emit_on_sync)
> >>+     , _M_needs_sync(__other._M_needs_sync)
> >>+      {
> >>+     __other._M_wrapped = nullptr;
> >>+      }
> >>+
> >>+      ~basic_syncbuf()
> >>+      {
> >>+     __try
> >>+       {
> >>+         emit();
> >>+       }
> >>+     __catch (...)
> >>+       { }
> >>+      }
> >>+
> >>+      basic_syncbuf& operator=(basic_syncbuf&& __other)
> >>+      {
> >>+     if (std::__addressof(__other) != this)
> >>+       {
> >>+         emit();
> >>+
> >>+         _M_impl = std::move(__other._M_impl);
> >>+         _M_wrapped = __other._M_wrapped; __other._M_wrapped = nullptr;
> >>+         _M_mtx = std::move(__other._M_mtx);
> >>+         _M_emit_on_sync = __other._M_emit_on_sync;
> >>+         _M_needs_sync = __other._M_needs_sync;
> >>+       }
> >>+     return *this;
> >>+      }
> >>+
> >>+      void
> >>+      swap(basic_syncbuf& __other)
> >>+      {
> >>+     if (std::__addressof(__other) != this)
> >>+       {
> >>+         std::swap(_M_impl, __other._M_impl);
> >>+         std::swap(_M_wrapped, __other._M_wrapped);
> >>+         std::swap(_M_mtx, __other._M_mtx);
> >>+         std::swap(_M_emit_on_sync, __other._M_emit_on_sync);
> >>+         std::swap(_M_needs_sync, __other._M_needs_sync);
> >>+       }
> >>+      }
> >>+
> >>+      bool
> >>+      emit()
> >>+      {
> >>+     if (!_M_wrapped)
> >>+       return false;
> >>+
> >>+     auto __s = _M_impl.view();
> >>+     if (__s.empty())
> >>+       return true;
> >>+
> >>+     const lock_guard<__mutex> __l(_M_mtx);
> >>+     if (_M_wrapped->sputn(__s.data(), __s.size()) != __s.size())
> >>+       return false;
> >>+
> >>+     if (_M_needs_sync)
> >>+       {
> >>+         _M_needs_sync = false;
> >>+         if (_M_wrapped->pubsync() != 0)
> >>+           return false;
> >>+       }
> >>+
> >>+     _M_impl.str("");
> >>+     return true;
> >>+      }
> >>+
> >>+      streambuf_type*
> >>+      get_wrapped() const noexcept
> >>+      { return _M_wrapped; }
> >>+
> >>+      allocator_type get_allocator() const noexcept
> >>+      { return _M_impl.get_allocator(); }
> >>+
> >>+      void
> >>+      set_emit_on_sync(bool __b) noexcept
> >>+      { _M_emit_on_sync = __b; }
> >>+
> >>+    protected:
> >>+      int
> >>+      sync() override
> >>+      {
> >>+     auto __res = _M_impl.pubsync();
> >>+     if (__res == 0)
> >>+       {
> >>+         _M_needs_sync = true;
> >>+         if (_M_emit_on_sync)
> >>+           return emit() ? 0 : -1;
> >>+       }
> >>+     return __res;
> >>+      }
> >>+
> >>+      streamsize
> >>+      xsputn(const char_type* __s, streamsize __n) override
> >>+      { return _M_impl.sputn(__s, __n); }
> >>+
> >>+    private:
> >>+      streambuf_type* _M_wrapped;
> >>+
> >>+      using __impl_type = basic_stringbuf<char_type, traits_type,
> >>+                                       allocator_type>;
> >>+      __impl_type _M_impl;
> >>+
> >>+      struct __mutex
> >>+      {
> >>+#if _GLIBCXX_HAS_GTHREADS
> >>+     mutex* _M_mtx;
> >>+
> >>+     __mutex(void* __t)
> >
> > Make this 'explicit' please.
> >
> >>+       : _M_mtx(__t ? &_S_get_mutex(__t) : nullptr)
> >>+     { }
> >>+
> >>+     void
> >>+     swap(__mutex& __other) noexcept
> >>+     { std::swap(_M_mtx, __other._M_mtx); }
> >>+
> >>+     void
> >>+     lock()
> >>+     {
> >>+       if (_M_mtx)
> >>+         _M_mtx->lock();
> >>+     }
> >>+
> >>+     void
> >>+     unlock()
> >>+     {
> >>+       if (_M_mtx)
> >>+         _M_mtx->unlock();
> >>+     }
> >>+
> >>+     // FIXME: This should be put in the .so
> >>+     static mutex&
> >>+     _S_get_mutex(void* __t)
> >>+     {
> >>+       const unsigned char __mask = 0xf;
> >>+       static mutex __m[__mask + 1];
> >>+
> >>+       auto __key = _Hash_impl::hash(__t) & __mask;
> >>+       return __m[__key];
> >>+     }
> >>+#else
> >>+     __mutex(void*)
> >
> > And 'explicit' here too.
> >
> >>+     { }
> >>+
> >>+     void
> >>+     swap(__mutex&&) noexcept
> >
> > This needs to be an lvalue reference, or it won't compile.
> >
> >>+     { }
> >>+
> >>+     void
> >>+     lock()
> >>+     { }
> >>+
> >>+     void
> >>+     unlock()
> >>+     { }
> >
> > All these completely empty functions can be put on one line:
> >
> >       void unlock() { }
> >
> > There's no need for these no-op members take up so many lines.
> >
> >>+#endif
> >>+     __mutex(const __mutex&) = delete;
> >>+     __mutex& operator=(const __mutex&) = delete;
> >
> > These are redundant (the user-declared moves below cause the copies to
> > be deleted) but harmless.
> >
> >>+
> >>+     __mutex(__mutex&&) = default;
> >>+     __mutex& operator=(__mutex&&) = default;
> >>+      };
> >>+      __mutex _M_mtx;
> >>+
> >>+      bool _M_emit_on_sync = false;
> >>+      bool _M_needs_sync = false;
> >>+    };
> >
> >
> > OK for trunk, thanks.
>

Reply via email to