Testsed x86_64-pc-linux-gnu, committed to master.

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