From 6bcbcea05884161d08da0c6386e48ac6e9ec3800 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Mon, 2 Nov 2020 10:06:06 -0800 Subject: [PATCH] libstdc++: Add c++2a libstdc++-v3/ChangeLog: * doc/doxygen/user.cfg.in (INPUT): Add new header. * include/Makefile.am (std_headers): Add new header. * include/Makefile.in: Regenerate. * include/precompiled/stdc++.h: Include new header. * include/std/syncstream: New header. * include/std/version: Add __cpp_lib_syncbuf. * testsuite/27_io/basic_syncbuf/1.cc: New test. * testsuite/27_io/basic_syncbuf/2.cc: Likewise. * testsuite/27_io/basic_syncbuf/basic_ops/1.cc: Likewise. * testsuite/27_io/basic_syncbuf/requirements/types.cc: Likewise. * testsuite/27_io/basic_syncbuf/sync_ops/1.cc: Likewise. * testsuite/27_io/basic_syncstream/1.cc: Likewise. * testsuite/27_io/basic_syncstream/2.cc: Likewise. * testsuite/27_io/basic_syncstream/basic_ops/1.cc: Likewise. * testsuite/27_io/basic_syncstream/requirements/types.cc: Likewise. --- libstdc++-v3/doc/doxygen/user.cfg.in | 1 + libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/precompiled/stdc++.h | 2 +- libstdc++-v3/include/std/syncstream | 333 ++++++++++++++++++ libstdc++-v3/include/std/version | 4 + .../testsuite/27_io/basic_syncbuf/1.cc | 28 ++ .../testsuite/27_io/basic_syncbuf/2.cc | 28 ++ .../27_io/basic_syncbuf/basic_ops/1.cc | 137 +++++++ .../27_io/basic_syncbuf/requirements/types.cc | 42 +++ .../27_io/basic_syncbuf/sync_ops/1.cc | 130 +++++++ .../testsuite/27_io/basic_syncstream/1.cc | 28 ++ .../testsuite/27_io/basic_syncstream/2.cc | 28 ++ .../27_io/basic_syncstream/basic_ops/1.cc | 134 +++++++ .../basic_syncstream/requirements/types.cc | 43 +++ 15 files changed, 939 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/include/std/syncstream create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/requirements/types.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_syncstream/requirements/types.cc diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in index 9b49a15d31b..320f6dea688 100644 --- a/libstdc++-v3/doc/doxygen/user.cfg.in +++ b/libstdc++-v3/doc/doxygen/user.cfg.in @@ -897,6 +897,7 @@ INPUT = @srcdir@/doc/doxygen/doxygroups.cc \ include/streambuf \ include/string \ include/string_view \ + include/syncstream \ include/system_error \ include/thread \ include/tuple \ diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index c90ac555e15..8652b921274 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -73,6 +73,7 @@ std_headers = \ ${std_srcdir}/shared_mutex \ ${std_srcdir}/span \ ${std_srcdir}/sstream \ + ${std_srcdir}/syncstream \ ${std_srcdir}/stack \ ${std_srcdir}/stdexcept \ ${std_srcdir}/stop_token \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index aa751f62c4f..4eb6b2b480a 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -419,6 +419,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..5e0864ec54a --- /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/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_mtx(__obuf) + { } + + basic_syncbuf(basic_syncbuf&& __other) + : _M_wrapped(__other._M_wrapped) + , _M_impl(std::move(__other._M_impl)) + , _M_mtx(std::move(__other._M_mtx)) + , _M_emit_on_sync(__other._M_emit_on_sync) + , _M_needs_sync(__other._M_needs_sync) + { + __other._M_wrapped = nullptr; + } + + ~basic_syncbuf() + { + __try + { + emit(); + } + __catch (...) + { } + } + + basic_syncbuf& operator=(basic_syncbuf&& __other) + { + if (std::__addressof(__other) != this) + { + emit(); + + _M_impl = std::move(__other._M_impl); + _M_wrapped = __other._M_wrapped; __other._M_wrapped = nullptr; + _M_mtx = std::move(__other._M_mtx); + _M_emit_on_sync = __other._M_emit_on_sync; + _M_needs_sync = __other._M_needs_sync; + } + return *this; + } + + void + swap(basic_syncbuf& __other) + { + if (std::__addressof(__other) != this) + { + std::swap(_M_impl, __other._M_impl); + std::swap(_M_wrapped, __other._M_wrapped); + std::swap(_M_mtx, __other._M_mtx); + std::swap(_M_emit_on_sync, __other._M_emit_on_sync); + std::swap(_M_needs_sync, __other._M_needs_sync); + } + } + + bool + emit() + { + if (!_M_wrapped) + return false; + + auto __s = _M_impl.view(); + if (__s.empty()) + return true; + + const lock_guard<__mutex> __l(_M_mtx); + if (_M_wrapped->sputn(__s.data(), __s.size()) != __s.size()) + return false; + + if (_M_needs_sync) + { + _M_needs_sync = false; + if (_M_wrapped->pubsync() != 0) + return false; + } + + _M_impl.str(""); + return true; + } + + streambuf_type* + get_wrapped() const noexcept + { return _M_wrapped; } + + allocator_type get_allocator() const noexcept + { return _M_impl.get_allocator(); } + + void + set_emit_on_sync(bool __b) noexcept + { _M_emit_on_sync = __b; } + + protected: + int + sync() override + { + auto __res = _M_impl.pubsync(); + if (__res == 0) + { + _M_needs_sync = true; + if (_M_emit_on_sync) + return emit() ? 0 : -1; + } + return __res; + } + + streamsize + xsputn(const char_type* __s, streamsize __n) override + { return _M_impl.sputn(__s, __n); } + + private: + streambuf_type* _M_wrapped; + + using __impl_type = basic_stringbuf; + __impl_type _M_impl; + + struct __mutex + { +#if _GLIBCXX_HAS_GTHREADS + mutex* _M_mtx; + + __mutex(void* __t) + : _M_mtx(__t ? &_S_get_mutex(__t) : nullptr) + { } + + void + swap(__mutex& __other) noexcept + { std::swap(_M_mtx, __other._M_mtx); } + + void + lock() + { + if (_M_mtx) + _M_mtx->lock(); + } + + void + unlock() + { + if (_M_mtx) + _M_mtx->unlock(); + } + + // FIXME: This should be put in the .so + static mutex& + _S_get_mutex(void* __t) + { + const unsigned char __mask = 0xf; + static mutex __m[__mask + 1]; + + auto __key = _Hash_impl::hash(__t) & __mask; + return __m[__key]; + } +#else + __mutex(void*) + { } + + void + swap(__mutex&&) noexcept + { } + + void + lock() + { } + + void + unlock() + { } +#endif + __mutex(const __mutex&) = delete; + __mutex& operator=(const __mutex&) = delete; + + __mutex(__mutex&&) = default; + __mutex& operator=(__mutex&&) = default; + }; + __mutex _M_mtx; + + 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..ef463996b31 --- /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; +} -- 2.30.2