From patchwork Thu Oct 15 14:46:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Rodgers X-Patchwork-Id: 1382712 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=appliantology.com Authentication-Results: ozlabs.org; dkim=pass (4096-bit key; secure) header.d=kolabnow.com header.i=@kolabnow.com header.a=rsa-sha256 header.s=dkim20160331 header.b=FE19J3F2; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CBsYN74HCz9sVL for ; Fri, 16 Oct 2020 01:46:31 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C2D8F3950C1A; Thu, 15 Oct 2020 14:46:28 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx.kolabnow.com (mx.kolabnow.com [95.128.36.41]) by sourceware.org (Postfix) with ESMTPS id D84FF3947403; Thu, 15 Oct 2020 14:46:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org D84FF3947403 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=appliantology.com Authentication-Results: sourceware.org; spf=none smtp.mailfrom=rodgert@appliantology.com Received: from localhost (unknown [127.0.0.1]) by ext-mx-out002.mykolab.com (Postfix) with ESMTP id 4AA1BBB2; Thu, 15 Oct 2020 16:46:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kolabnow.com; h= content-transfer-encoding:mime-version:message-id:date:date :subject:subject:from:from:received:received:received; s= dkim20160331; t=1602773174; x=1604587575; bh=BoTKlq5HGQli3VxFakJ kcO3qw86gwhAqyFaGYLxLets=; b=FE19J3F29OH/ey3a6Hm8DEF+DWo7UWxmjVx F0V3VSIarOca+fcJ4XiPo9qss4GDiKSszonveLj4G0DkQXGeqpHdpGa/bBeVrXwb q5nb+OONbKQoY47ymouoiqp2KZyRyg7Gsksp4Qprhh4ujE2278QiW59x072Umeh1 aA8Nxhn48SBxckLaLbyc4E7xYTJ+o5ixv89dPhUvnMpo/gXTJiI4HAEnOWXVCVe6 DOtWUI1Ry29vrjJb3fwEIJvcP/sDSbdzXjaAijrRgDvEUxcsmN246HFVpd0kRfZy c0J5BzQDeCSwcwZXu2uFGRhMB2fHBnjfxH/fSUigv3GgMAzvD0I/DqhHP9oHPla6 LFhM7jmNgjQL5g/JklSiQnNOQ2rPMEPXK0tAVXds+BD7C/utkYS/ZBfmOmlP6CsS NcuD4WQ6BdN5IEsftcwqjqaH1egU3vux0RGwiMvVG5mlzuE+Y98/4f15VFIQA5xV N62Bvfzdh9ivyqFn4w0TrWMdVow7wd082a/JZEafU9kVrNJ0/JFtzeY67xf6rIaw jklE5WyfY6LZ0uvtpQduUBrYwh8Rg2pvJ9iWxO+GLm8rMpr8I+Ymep6Nxxz80fjf MYefpKgibvwV8UI1pxZ70cnnhPpEtjUt7FH0VhJCUK4a4EZaV5Nc5cSEblcZSge/ pVuM/F+4= X-Virus-Scanned: amavisd-new at mykolab.com X-Spam-Score: -1.9 X-Spam-Level: X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.2 Received: from mx.kolabnow.com ([127.0.0.1]) by localhost (ext-mx-out002.mykolab.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HTJb_cNkrhtX; Thu, 15 Oct 2020 16:46:14 +0200 (CEST) Received: from int-mx003.mykolab.com (unknown [10.9.13.3]) by ext-mx-out002.mykolab.com (Postfix) with ESMTPS id D216E1AC; Thu, 15 Oct 2020 16:46:13 +0200 (CEST) Received: from ext-subm001.mykolab.com (unknown [10.9.6.1]) by int-mx003.mykolab.com (Postfix) with ESMTPS id 6D6092556; Thu, 15 Oct 2020 16:46:13 +0200 (CEST) From: Thomas Rodgers To: gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org Subject: [PATCH] libstdc++: Add c++2a Date: Thu, 15 Oct 2020 07:46:06 -0700 Message-Id: <20201015144606.1402141-1-rodgert@appliantology.com> MIME-Version: 1.0 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: trodgers@redhat.com Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" From: Thomas Rodgers * Note: depends on a sufficiently C++20ified basic_stringbuf<>. libstdc++/Changelog: libstdc++-v3/include/Makefile.am (std_headers): Add new header. libstdc++-v3/include/Makefile.in: Regenerate. libstdc++-v3/include/std/streambuf (__detail::__streambuf_core_access): Define. (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/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/std/streambuf | 81 +++++ 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 | 27 ++ .../27_io/basic_syncbuf/basic_ops/1.cc | 138 ++++++++ .../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 | 27 ++ .../27_io/basic_syncstream/basic_ops/1.cc | 135 +++++++ .../basic_syncstream/requirements/types.cc | 43 +++ 14 files changed, 1018 insertions(+) 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/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 28d273924ee..61aaff7a2f4 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/std/streambuf b/libstdc++-v3/include/std/streambuf index cae35e75bda..d6053e4c1ed 100644 --- a/libstdc++-v3/include/std/streambuf +++ b/libstdc++-v3/include/std/streambuf @@ -48,6 +48,84 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #define _IsUnused __attribute__ ((__unused__)) + template + class basic_streambuf; + +#if __cplusplus > 201703L + namespace __detail + { + struct __streambuf_core_access + { + template + static void + _S_imbue(basic_streambuf<_CharT, _Traits>& __b, const locale& __loc) + { __b.imbue(__loc); } + + template + static basic_streambuf<_CharT, _Traits>* + _S_setbuf(basic_streambuf<_CharT, _Traits>& __b, + _CharT* __c, streamsize __n) + { return __b.setbuf(__c, __n); } + + template + static typename _Traits::pos_type + _S_seekoff(basic_streambuf<_CharT, _Traits>& __b, + typename _Traits::off_type __off, ios_base::seekdir __dir, + ios_base::openmode __mode) + { return __b.seekoff(__off, __dir, __mode); } + + template + static typename _Traits::pos_type + _S_seekpos(basic_streambuf<_CharT, _Traits>& __b, + typename _Traits::pos_type __pos, ios_base::openmode __mode) + { return __b.seekpos(__pos, __mode); } + + template + static int + _S_sync(basic_streambuf<_CharT, _Traits>& __b) + { return __b.sync(); } + + template + static streamsize + _S_showmanyc(basic_streambuf<_CharT, _Traits>& __b) + { return __b.showmanyc(); } + + template + static streamsize + _S_xsgetn(basic_streambuf<_CharT, _Traits>& __b, _CharT* __s, streamsize __n) + { return __b.xsgetn(__s, __n); } + + template + static typename _Traits::int_type + _S_underflow(basic_streambuf<_CharT, _Traits>& __b) + { return __b.underflow(); } + + template + static typename _Traits::int_type + _S_uflow(basic_streambuf<_CharT, _Traits>& __b) + { return __b.uflow(); } + + template + static typename _Traits::int_type + _S_pbackfail(basic_streambuf<_CharT, _Traits>& __b, + typename _Traits::int_type __c) + { return __b.pbackfail(__c); } + + template + static streamsize + _S_xsputn(basic_streambuf<_CharT, _Traits>& __b, + const typename _Traits::char_type* __s, streamsize __n) + { return __b.xsputn(__s, __n); } + + template + typename _Traits::int_type + _S_overflow(basic_streambuf<_CharT, _Traits>& __b, + typename _Traits::int_type __c) + { return __b.overflow(__c); } + }; + } +#endif // C++20 + template streamsize __copy_streambufs_eof(basic_streambuf<_CharT, _Traits>*, @@ -456,6 +534,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return this->xsputn(__s, __n); } protected: +#if __cplusplus > 201703L + friend __detail::__streambuf_core_access; +#endif /** * @brief Base constructor. * diff --git a/libstdc++-v3/include/std/syncstream b/libstdc++-v3/include/std/syncstream new file mode 100644 index 00000000000..0a034ed03f4 --- /dev/null +++ b/libstdc++-v3/include/std/syncstream @@ -0,0 +1,333 @@ +// -*- 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 +// . + +/** @file include/ranges + * This is a Standard C++ Library header. + */ + + #ifndef _GLIBCXX_SYNCSTREAM + #define _GLIBCXX_SYNCSTREAM 1 + +#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI + +#define __cpp_lib_syncbuf 201803L + +#pragma GCC system_header + +#include +#include +#include +#include + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template, + 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) + { } + + 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 ? &_S_get_mutex(__obuf) : nullptr) + { } + + basic_syncbuf(basic_syncbuf&& __other) + : _M_wrapped(__other._M_wrapped) + , _M_impl(std::move(__other._M_impl)) + , _M_mtx(__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 (&__other != this) + { + emit(); + _M_wrapped = __other._M_wrapped; __other._M_wrapped = nullptr; + _M_impl = std::move(__other._M_impl); + _M_mtx = __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 (&__other != this) + { + std::swap(_M_wrapped, __other._M_wrapped); + std::swap(_M_impl, __other._M_impl); + 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 __l(*_M_mtx); + auto __xsz = _M_wrapped->sputn(__s.data(), __s.size()); + + if (__xsz != __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: + void + imbue(const locale& __loc) override + { __detail::__streambuf_core_access::_S_imbue(_M_impl, __loc); } + + basic_streambuf* + setbuf(char_type* __c, streamsize __n) override + { + return __detail::__streambuf_core_access::_S_setbuf(_M_impl, __c, __n); + } + + pos_type + seekoff(off_type __off, ios_base::seekdir __dir, + ios_base::openmode __mode) override + { + return __detail::__streambuf_core_access::_S_seekoff(_M_impl, __off, + __dir, __mode); + } + + pos_type + seekpos(pos_type __pos, ios_base::openmode __mode) override + { + return __detail::__streambuf_core_access::_S_seekpos(_M_impl, + __pos, __mode); + } + + int + sync() override + { + auto __res = __detail::__streambuf_core_access::_S_sync(_M_impl); + if (__res == 0) + { + _M_needs_sync = true; + if (_M_emit_on_sync) + return emit() ? 0 : -1; + } + return __res; + } + + streamsize + showmanyc() override + { return __detail::__streambuf_core_access::_S_showmanyc(_M_impl); } + + streamsize + xsgetn(char_type* __s, streamsize __n) override + { + return __detail::__streambuf_core_access::_S_xsgetn(_M_impl, __s, __n); + } + + int_type + underflow() override + { return __detail::__streambuf_core_access::_S_underflow(_M_impl); } + + int_type + uflow() override + { return __detail::__streambuf_core_access::_S_uflow(_M_impl); } + + int_type + pbackfail(int_type __c) override + { return __detail::__streambuf_core_access::_S_pbackfail(_M_impl, __c); } + + streamsize + xsputn(const char_type* __s, streamsize __n) override + { + return __detail::__streambuf_core_access::_S_xsputn(_M_impl, __s, __n); + } + + private: + streambuf_type* _M_wrapped; + + using __impl_type = basic_stringbuf; + __impl_type _M_impl; + mutex* _M_mtx; + + bool _M_emit_on_sync = false; + bool _M_needs_sync = false; + + static constexpr size_t _S_small_size = 128; + + 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]; + } + }; + + template , + typename _Alloc = allocator<_CharT>> + class basic_osyncstream : public basic_ostream<_CharT, _Traits> + { + public: + // Types: + using char_type = _CharT; + using traits_type = _Traits; + using allocator_type = _Alloc; + using int_type = typename traits_type::int_type; + using pos_type = typename traits_type::pos_type; + using off_type = typename traits_type::off_type; + using syncbuf_type = basic_syncbuf<_CharT, _Traits, _Alloc>; + using streambuf_type = typename syncbuf_type::streambuf_type; + + using __ostream_type = basic_ostream<_CharT, _Traits>; + + private: + syncbuf_type _M_syncbuf; + + public: + basic_osyncstream(streambuf_type* __buf, const allocator_type& __a) + : _M_syncbuf(__buf, __a) + { this->init(&_M_syncbuf); } + + explicit basic_osyncstream(streambuf_type* __buf) + : _M_syncbuf(__buf) + { this->init(&_M_syncbuf); } + + basic_osyncstream(basic_ostream& __os, + const allocator_type& __a) + : basic_osyncstream(__os.rdbuf(), __a) + { this->init(&_M_syncbuf); } + + explicit basic_osyncstream(basic_ostream& __os) + : basic_osyncstream(__os.rdbuf()) + { this->init(&_M_syncbuf); } + + basic_osyncstream(basic_osyncstream&& __rhs) noexcept + : __ostream_type(std::move(__rhs)), + _M_syncbuf(std::move(__rhs._M_syncbuf)) + { __ostream_type::set_rdbuf(&_M_syncbuf); } + + ~basic_osyncstream() = default; + + basic_osyncstream& operator=(basic_osyncstream&& __rhs) noexcept + { + if (&__rhs != this) + { + __ostream_type::operator=(std::move(__rhs)); + _M_syncbuf = std::move(__rhs._M_syncbuf); + __ostream_type::set_rdbuf(&_M_syncbuf); + } + return *this; + } + + syncbuf_type* rdbuf() const noexcept + { return const_cast(&_M_syncbuf); } + + streambuf_type* get_wrapped() const noexcept + { return _M_syncbuf.get_wrapped(); } + + void emit() + { _M_syncbuf.emit(); } + }; + + template + inline void + swap(basic_syncbuf<_CharT, _Traits, _Allocator>& __x, + basic_syncbuf<_CharT, _Traits, _Allocator>& __y) + { __x.swap(__y); } + + using syncbuf = basic_syncbuf; + using wsyncbuf = basic_syncbuf; + + using osyncstream = basic_osyncstream; + using wosyncstream = basic_osyncstream; +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++2a +#endif /* _GLIBCXX_SYNCSTREAM */ + diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index d5d42ed0a72..8681d70fbfa 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -215,6 +215,10 @@ #define __cpp_lib_interpolate 201902L #ifdef _GLIBCXX_HAS_GTHREADS # define __cpp_lib_jthread 201911L +# ifdef _GLIBCXX_USE_CXX11_ABI +// Only supported with cx11-abi +# define __cpp_lib_syncbuf 201803L +# endif #endif #define __cpp_lib_list_remove_return_type 201806L #define __cpp_lib_math_constants 201907L diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc new file mode 100644 index 00000000000..ebea9becdb3 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc @@ -0,0 +1,28 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } +// { dg-require-effective-target cxx11-abi } + +#include + +#ifndef __cpp_lib_syncbuf +# error "Feature-test macro for syncbuf missing in " +#elif __cpp_lib_syncbuf!= 201803L +# error "Feature-test macro for syncbuf has wrong value in " +#endif diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc new file mode 100644 index 00000000000..43538f89fb8 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/2.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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +#ifndef __cpp_lib_syncbuf +# error "Feature-test macro for syncbuf missing in " +#elif __cpp_lib_syncbuf!= 201803L +# error "Feature-test macro for syncbuf has wrong value in " +#endif diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc new file mode 100644 index 00000000000..98e00dea1f1 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc @@ -0,0 +1,138 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a -pthread" } +// { dg-do run { target c++2a } } +// { dg-require-effective-target pthread } +// { dg-require-effective-target cxx11-abi } +// { dg-require-gthreads "" } + +#include +#include +#include + +#include +#include + +void +test01() // construction +{ + { + std::syncbuf s1; + VERIFY( s1.get_wrapped() == nullptr ); + + std::stringbuf b; + std::syncbuf s2(&b); + VERIFY( s2.get_wrapped() == &b ); + } + + { + using alloc_type = __gnu_test::uneq_allocator; + using sbuf_t = std::basic_syncbuf, + alloc_type>; + + sbuf_t b; + + alloc_type aa; + sbuf_t s1(&b, aa); + VERIFY( aa == s1.get_allocator() ); + + alloc_type aaa(42); + sbuf_t s2(&b, aaa); + VERIFY( aaa == s2.get_allocator() ); + + VERIFY( s1.get_allocator() != s2.get_allocator() ); + } +} + +void +test02() // moving +{ + { + std::stringbuf b; + std::syncbuf s1(&b); + + std::syncbuf s2(std::move(s1)); + + VERIFY( s1.get_wrapped() == nullptr ); + VERIFY( s2.get_wrapped() == &b ); + } + + { + std::stringbuf b; + std::syncbuf s1(&b); + + std::syncbuf s2; + s2 = std::move(s1); + + VERIFY( s1.get_wrapped() == nullptr ); + VERIFY( s2.get_wrapped() == &b ); + } +} + +void +test03() // swaping +{ + std::stringbuf b; + std::syncbuf s1(&b); + + std::syncbuf s2; + std::swap(s1, s2); + + VERIFY( s1.get_wrapped() == nullptr ); + VERIFY( s2.get_wrapped() == &b ); +} + +void +test04() // emitting +{ + { + std::stringbuf b; + std::syncbuf s(&b); + + const std::string_view txt("This is a test"); + s.sputn(txt.data(), txt.size()); + + VERIFY( b.str() != txt ); + VERIFY( s.pubsync() == 0 ); + VERIFY( b.str() != txt ); + + VERIFY( s.emit() ); + VERIFY( b.str() == txt ); + } + + { + std::stringbuf b; + std::syncbuf s(&b); + s.set_emit_on_sync(true); + + const std::string_view txt("This is a test"); + s.sputn(txt.data(), txt.size()); + + VERIFY( s.pubsync() == 0 ); + VERIFY( b.str() == txt ); + } +} + +int main() +{ + test01(); + test02(); + test03(); + test04(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc new file mode 100644 index 00000000000..49266b4abf0 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc @@ -0,0 +1,42 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } +// { dg-require-effective-target cxx11-abi } + +#include + +template + struct type_reqs + { + using test_type = T; + using char_type = test_type::char_type; + using int_type = test_type::int_type; + using pos_type = test_type::pos_type; + using off_Type = test_type::off_type; + using traits_type = test_type::traits_type; + using allocator_type = test_type::allocator_type; + using streambuf_type = test_type::streambuf_type; + }; + +void test01() +{ + // Check for required typedefs + using test_type = type_reqs; + using wtest_type = type_reqs; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc new file mode 100644 index 00000000000..097da110178 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc @@ -0,0 +1,130 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a -pthread -Wl,--no-demangle" } +// { dg-do run { target c++2a } } +// { dg-require-effective-target pthread } +// { dg-require-effective-target cxx11-abi } +// { dg-require-gthreads "" } + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int +main() +{ + using namespace std::chrono_literals; + + std::stringbuf b; + std::atomic running(0); + + auto const cstr = "This is a test"; + + constexpr int ct = 1000; + auto const body = [&]{ + ++running; + auto tid = std::this_thread::get_id(); + std::syncbuf s(&b); + for (auto i = 0; i < ct; ++i) + { + std::stringstream stm; + stm << tid << ' ' << cstr << ' ' << i << std::endl; + auto sv = stm.view(); + s.sputn(sv.data(), sv.size()); + VERIFY( s.emit() ); + } + }; + + const auto tct = 8; + std::vector ts; + ts.reserve(tct); + + for (auto i = 0; i < tct; ++i) + ts.emplace_back(std::thread(body)); + + do + { + std::this_thread::sleep_for(100ms); + } + while (running.load() < tct); + + std::unordered_map tids; + for (auto&& t : ts) + { + std::stringstream stm; + stm << t.get_id(); + tids.emplace(std::make_pair(stm.str(), 0)); + }; + + for (auto&& t : ts) + t.join(); + + std::vector lines; + const auto lct = ct * ts.size(); + lines.reserve(lct); + + std::size_t last = 0; + auto sv = b.view(); + auto p = sv.find('\n'); + while (p != std::string_view::npos) + { + lines.emplace_back(sv.substr(last, p - last)); + last = p+1; + p = sv.find('\n', last); + } + VERIFY( lines.size() == lct ); + + auto sep = ""; + auto i = 0; + sv = std::string_view(cstr); + + for (auto&& l : lines) + { + auto p = l.find(' '); + VERIFY( p != std::string_view::npos ); + std::string tid(l.substr(0, p)); + ++p; + + VERIFY( l.substr(p, sv.size()) == sv ); + std::string s(l.substr(++p + sv.size())); + std::stringstream stm(s); + int n; + stm >> n; + VERIFY( stm.eof() ); + VERIFY( n >= 0 && n < ct ); + auto it = tids.find(tid); + VERIFY( it != std::end(tids) ); + ++(it->second); + } + + for (auto const& t : tids) + { + VERIFY( t.second == ct ); + } + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc new file mode 100644 index 00000000000..ebea9becdb3 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc @@ -0,0 +1,28 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } +// { dg-require-effective-target cxx11-abi } + +#include + +#ifndef __cpp_lib_syncbuf +# error "Feature-test macro for syncbuf missing in " +#elif __cpp_lib_syncbuf!= 201803L +# error "Feature-test macro for syncbuf has wrong value in " +#endif diff --git a/libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc b/libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc new file mode 100644 index 00000000000..43538f89fb8 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/2.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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +#ifndef __cpp_lib_syncbuf +# error "Feature-test macro for syncbuf missing in " +#elif __cpp_lib_syncbuf!= 201803L +# error "Feature-test macro for syncbuf has wrong value in " +#endif diff --git a/libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc new file mode 100644 index 00000000000..e2cb6404cbe --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc @@ -0,0 +1,135 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a -pthread" } +// { dg-do run { target c++2a } } +// { dg-require-effective-target pthread } +// { dg-require-effective-target cxx11-abi } +// { dg-require-gthreads "" } + +#include +#include +#include +#include +#include + +void +test01() // construction +{ + { + std::stringbuf b; + std::osyncstream s(&b); + VERIFY( s.rdbuf() != nullptr ); + VERIFY( s.get_wrapped() == &b ); + } + + { + std::ostringstream stm; + std::osyncstream s(stm); + VERIFY( s.get_wrapped() == stm.rdbuf() ); + } + + { + using alloc_type = __gnu_test::uneq_allocator; + using sbuf_t = std::basic_syncbuf, + alloc_type>; + using stream_t = std::basic_osyncstream, + alloc_type>; + using str_t = std::basic_ostringstream, + alloc_type>; + sbuf_t b; + + alloc_type aa; + stream_t s1(&b, aa); + VERIFY( aa == s1.rdbuf()->get_allocator() ); + + alloc_type aaa(42); + stream_t s2(&b, aaa); + VERIFY( aaa == s2.rdbuf()->get_allocator() ); + + VERIFY( s1.rdbuf()->get_allocator() != s2.rdbuf()->get_allocator() ); + + str_t stm; + stream_t s3(stm, aa); + VERIFY( s3.get_wrapped() == stm.rdbuf() ); + VERIFY( aa == s1.rdbuf()->get_allocator() ); + } +} + +void +test02() // moving +{ + { + std::stringbuf b; + std::osyncstream s1(&b); + + std::osyncstream s2(std::move(s1)); + + VERIFY( s1.get_wrapped() == nullptr ); + VERIFY( s2.get_wrapped() == &b ); + } + + { + std::stringbuf b1; + std::osyncstream s1(&b1); + + std::stringbuf b2; + std::osyncstream s2(&b2); + s2 = std::move(s1); + + VERIFY( s1.get_wrapped() == nullptr ); + VERIFY( s2.get_wrapped() == &b1 ); + } +} + +void +test03() // swaping +{ + std::stringbuf b1; + std::osyncstream s1(&b1); + + std::stringbuf b2; + std::osyncstream s2(&b2); + + std::swap(s1, s2); + + VERIFY( s1.get_wrapped() == &b2 ); + VERIFY( s2.get_wrapped() == &b1 ); +} + +void +test04() // emitting +{ + { + std::stringbuf b; + std::osyncstream s(&b); + + const std::string_view txt("This is a test"); + s << txt; + + s.emit(); + VERIFY( b.str() == txt ); + } +} +int main() +{ + test01(); + test02(); + test03(); + test04(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc b/libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc new file mode 100644 index 00000000000..dfc0b72efcd --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc @@ -0,0 +1,43 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } +// { dg-require-effective-target cxx11-abi } + +#include + +template + struct type_reqs + { + using test_type = T; + using char_type = test_type::char_type; + using int_type = test_type::int_type; + using pos_type = test_type::pos_type; + using off_Type = test_type::off_type; + using traits_type = test_type::traits_type; + using allocator_type = test_type::allocator_type; + using streambuf_type = test_type::streambuf_type; + using syncbuf_type = test_type::syncbuf_type; + }; + +void test01() +{ + // Check for required typedefs + using test_type = type_reqs; + using wtest_type = type_reqs; +}