From patchwork Fri Oct 16 00:24:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Rodgers X-Patchwork-Id: 1383000 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=8.43.85.97; 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=VhU1+xJQ; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 4CC6P66281z9sTm for ; Fri, 16 Oct 2020 11:25:12 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AF59C3851C08; Fri, 16 Oct 2020 00:25:08 +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 E66973858C27; Fri, 16 Oct 2020 00:24:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org E66973858C27 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-out003.mykolab.com (Postfix) with ESMTP id 6B18E41152; Fri, 16 Oct 2020 02:24:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kolabnow.com; h= content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:date:subject:subject:from:from:received :received:received; s=dkim20160331; t=1602807878; x=1604622279; bh=zN7oRdlXszCzlRO7LzCTdgH0Zeh3sPO7bSuGFjN+HXg=; b=VhU1+xJQf7u9 iJbdT1xAZBsb7mL/vwxb0S5sWPrF6+CF7LgW1xO547GB/NXCDNn30ZCZcFOnxbbA RYo+SY6WRyDXy8RO7ULLLlziwd3UA7R+aAK5wPNG1MHbY8bLOfYXH1q9TflcWthX rat9O0EEspC3u1daRHbZpkOSBxUNdLQEpBWoDl60coaOB2/4bAy8748N3+Qn1F9I vi3Kxt9WspVzfW1cfAYBalJ6mA8Hq1Cl8xUCfVNODFrm/v/r1PKtk0jG6XQgm2Zq AyQCoR3Rc7gGhTWDYBHcEEiP0j3RxzUPZwou48FTsgUGseTyHeBS8V6GBfCa4Dma 25T30G1fmW1/96Sv6PPKbiEnn41yLG28MRPqcERTUz8Cs3zBvvr4p4fQhX5828Wh vSORyIpSoMfDGD2BLLgIc20BKA3vd5xaJheRKziinM63jMw4umcQy/j1/bsVn9hT 5O7UrWIjzn5mty12NP6HV5uLTGLKL9XxLLvT8r09Rb8p/cnX3aPhey3KuqlN8xRw noMdK8MK84XxaX5VDuh3J6sxpKksv/A+UG9tOgns00C9hcHymLI9Tz+Kx0ThgpQc s+f2I/nryafM1gAQeX7MclhGTR+B21KyCp5rNtRSuxBjxjARNPX9DXTOkfy8Vhh3 CxEoEoC7yFfcuRooULuNV2Da/TLLfMk= 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-out003.mykolab.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id h9cLKPh_CcoI; Fri, 16 Oct 2020 02:24:38 +0200 (CEST) Received: from int-mx002.mykolab.com (unknown [10.9.13.2]) by ext-mx-out003.mykolab.com (Postfix) with ESMTPS id C2A08410EF; Fri, 16 Oct 2020 02:24:37 +0200 (CEST) Received: from ext-subm003.mykolab.com (unknown [10.9.6.3]) by int-mx002.mykolab.com (Postfix) with ESMTPS id 5CBF83384; Fri, 16 Oct 2020 02:24:37 +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 17:24:30 -0700 Message-Id: <20201016002430.1662430-1-rodgert@appliantology.com> In-Reply-To: <20201015192923.GJ3402@redhat.com> References: <20201015192923.GJ3402@redhat.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 This should address the cumulative comments (modulo the discussion going on on the reflector about specification issues/questions). 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: Includ new header. 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/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/sstream | 2 +- libstdc++-v3/include/std/syncstream | 276 ++++++++++++++++++ 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 +++ 16 files changed, 883 insertions(+), 2 deletions(-) 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 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/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 #include #include -// #include +#include #include #endif diff --git a/libstdc++-v3/include/std/sstream b/libstdc++-v3/include/std/sstream index b0d1decfe63..5379f025eef 100644 --- a/libstdc++-v3/include/std/sstream +++ b/libstdc++-v3/include/std/sstream @@ -137,7 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // 27.8.2.2 Assign and swap: basic_stringbuf& - operator=(const basic_stringbuf&) = delete; + operator=(const basic_stringbuf&) = delete; basic_stringbuf& operator=(basic_stringbuf&& __rhs) diff --git a/libstdc++-v3/include/std/syncstream b/libstdc++-v3/include/std/syncstream new file mode 100644 index 00000000000..96bc67a9713 --- /dev/null +++ b/libstdc++-v3/include/std/syncstream @@ -0,0 +1,276 @@ +// -*- 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/syncstream + * 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, 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 ? &_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 (std::__addressof(__other) != this) + { + emit(); + + _M_impl = std::move(__other._M_impl); + _M_wrapped = __other._M_wrapped; __other._M_wrapped = nullptr; + _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 (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 __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: + 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; + __impl_type _M_impl; + mutex* _M_mtx; + + bool _M_emit_on_sync = false; + bool _M_needs_sync = false; + + // 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]; + } + }; + + template , + typename _Alloc = allocator<_CharT>> + class basic_osyncstream : public basic_ostream<_CharT, _Traits> + { + using __ostream_type = 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; + + private: + syncbuf_type _M_syncbuf; + + public: + basic_osyncstream(streambuf_type* __buf, const allocator_type& __a) + : _M_syncbuf(__buf, __a) + { this->init(std::__addressof(_M_syncbuf)); } + + explicit basic_osyncstream(streambuf_type* __buf) + : _M_syncbuf(__buf) + { this->init(std::__addressof(_M_syncbuf)); } + + basic_osyncstream(basic_ostream& __os, + const allocator_type& __a) + : basic_osyncstream(__os.rdbuf(), __a) + { this->init(std::__addressof(_M_syncbuf)); } + + explicit basic_osyncstream(basic_ostream& __os) + : basic_osyncstream(__os.rdbuf()) + { this->init(std::__addressof(_M_syncbuf)); } + + basic_osyncstream(basic_osyncstream&& __rhs) noexcept + : __ostream_type(std::move(__rhs)), + _M_syncbuf(std::move(__rhs._M_syncbuf)) + { __ostream_type::set_rdbuf(std::__addressof(_M_syncbuf)); } + + ~basic_osyncstream() = default; + + basic_osyncstream& operator=(basic_osyncstream&&) noexcept = default; + + 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) noexcept + { __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; +}