From patchwork Thu Oct 29 21:12:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Rodgers X-Patchwork-Id: 1390365 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=DasF2SAN; 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 4CMdTh6Gbqz9sRK for ; Fri, 30 Oct 2020 08:13:42 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C396B398782B; Thu, 29 Oct 2020 21:13:36 +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 2F5D53857C77; Thu, 29 Oct 2020 21:13:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 2F5D53857C77 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 66E5340701; Thu, 29 Oct 2020 22:13:30 +0100 (CET) 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=1604006007; x=1605820408; bh=WoXCcw4QWr2Ak0uuB5f7boy6hiinyqzEVjd4KZh7JYA=; b=DasF2SANxHzI 7V0Or/VjMWWtjYYMa/0zYSjclo4Nc1jK3iZpqXntpEWFtY54AjEAO6HY04bUCv18 HFp5C1Kh9w2fsH6SHFKiIYLl/zBGi4FMAQ1l5T7P7EgLZOW2xYs+y6uLlqjTl77X vzsXjX8vIofM86e1ZNsSaxCw6aJGdr0BBpiSik1se0jJPoxc4DdDc0x6RM/aV7S/ kdPaBJkwYApCPylfrX6OzhGYW4t9V8tlGnBcVQ4gL/6j98v0jB8Htro4Z3NQioeM mrICnWaWEJl5e8nAVEb97i7YtKIQoHalyHK4a8TbbKTgfUCeCpu4+8iqwFCOY8tH AXJ66g39EzLCvB18Hh6Rf1B49VBqlNAbKLGljV8nnl8TrWrxn6Y8KinKifUH5HSZ 0K8FJ2SG1r4Znl0Pv5rP6QIAaCrE9IJwHkTZ4GxqyNqpiE9EWQmPrW/48pW6QQDi +8KBlbH3zTI4Bej/GPIql8KvXGxuKKT9M617K7TV7KUh6tB+AomODagqfqWM8JOk TKqQtFNs4aqNd/SxJbguFwOkZKiWeIJvlyzdUzNffub/wjd+mI9QCd+miOLOq4OB KjHX6Xrld1k323Pa9ZdDGcCDBCVe+YJCn4UAwiCI1mLpEQIGnGKZHp/zIoJZ66lp YHEPGFEylgYpTpYyPz7+DGOy6bj8FW0= X-Virus-Scanned: amavisd-new at mykolab.com X-Spam-Score: -1.9 X-Spam-Level: X-Spam-Status: No, score=-12.6 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 v0pQJN5tkeB0; Thu, 29 Oct 2020 22:13:27 +0100 (CET) Received: from int-mx003.mykolab.com (unknown [10.9.13.3]) by ext-mx-out003.mykolab.com (Postfix) with ESMTPS id 9D22E404DA; Thu, 29 Oct 2020 22:13:27 +0100 (CET) Received: from ext-subm002.mykolab.com (unknown [10.9.6.2]) by int-mx003.mykolab.com (Postfix) with ESMTPS id 36C47A3F; Thu, 29 Oct 2020 22:13:27 +0100 (CET) From: Thomas Rodgers To: gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org Subject: [PATCH] libstdc++: Add c++2a Date: Thu, 29 Oct 2020 14:12:13 -0700 Message-Id: <20201029211212.1465538-1-rodgert@appliantology.com> In-Reply-To: <20201029161814.GC503596@redhat.com> References: <20201029161814.GC503596@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 Addresses latest patch feedback. Changes to also work on single threaded configurations. 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 | 328 ++++++++++++++++++ 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, 934 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 #include #include -// #include +#include #include #endif diff --git a/libstdc++-v3/include/std/syncstream b/libstdc++-v3/include/std/syncstream new file mode 100644 index 00000000000..88452c2ed10 --- /dev/null +++ b/libstdc++-v3/include/std/syncstream @@ -0,0 +1,328 @@ +// -*- 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 + +#include +#if _GLIBCXX_USE_CXX11_ABI + +#define __cpp_lib_syncbuf 201803L + +#pragma GCC system_header + +#include + +#include +#include +#include +#include + +#if _GLIBCXX_HAS_GTHREADS +# include +#endif + +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_locker(__obuf) + { } + + basic_syncbuf(basic_syncbuf&& __other) + : _M_wrapped(__other._M_wrapped) + , _M_impl(std::move(__other._M_impl)) + , _M_locker(std::move(__other._M_locker)) + , _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_locker = std::move(__other._M_locker); + _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_locker, __other._M_locker); + 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; + + auto res = _M_locker([&, this] + { + 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; + __impl_type _M_impl; + + struct __with_lock + { +#if _GLIBCXX_HAS_GTHREADS + mutex* _M_mtx; + + __with_lock(void* __t) + : _M_mtx(__t ? &_S_get_mutex(__t) : nullptr) + { } + + void + swap(__with_lock& __other) noexcept + { std::swap(_M_mtx, __other._M_mtx); } + + template + bool + operator()(_Func __f) + { + const lock_guard __l(*_M_mtx); + return __f(); + } + + // 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 + __with_lock(void*) + { } + + void + swap(__with_lock&) noexcept + { } + + template + bool + operator()(_Func && __f) + { + return __f(); + } +#endif + __with_lock(const __with_lock&) = delete; + __with_lock& operator=(const __with_lock&) = delete; + + __with_lock(__with_lock&&) = default; + __with_lock& operator=(__with_lock&&) = default; + }; + __with_lock _M_locker; + + bool _M_emit_on_sync = false; + bool _M_needs_sync = false; + }; + + 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() + { + if (!_M_syncbuf.emit()) + this->setstate(ios_base::failbit); + } + }; + + 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 // _GLIBCXX_USE_CXX11_ABI +#endif // C++2a +#endif /* _GLIBCXX_SYNCSTREAM */ diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index ebb50a04d24..7f51ef3a6c4 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -229,6 +229,10 @@ #define __cpp_lib_span 202002L #define __cpp_lib_ssize 201902L #define __cpp_lib_starts_ends_with 201711L +# if _GLIBCXX_USE_CXX11_ABI +// Only supported with cx11-abi +# define __cpp_lib_syncbuf 201803L +# endif #define __cpp_lib_to_address 201711L #define __cpp_lib_to_array 201907L #endif 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..1b3ae9330bb --- /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..4ffcb0410fd --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/2.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/basic_ops/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc new file mode 100644 index 00000000000..d5062bab70b --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc @@ -0,0 +1,137 @@ +// 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-additional-options "-pthread" { target pthread } } +// { dg-do run { target c++2a } } +// { dg-require-effective-target cxx11-abi } + +#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..90d20f1a607 --- /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" } +// { 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..1b3ae9330bb --- /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..4ffcb0410fd --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/2.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/basic_ops/1.cc b/libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc new file mode 100644 index 00000000000..a40cd162fbd --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc @@ -0,0 +1,134 @@ +// 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-additional-options "-pthread" { target pthread } } +// { dg-do run { target c++2a } } +// { dg-require-effective-target cxx11-abi } + +#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; +}