libstdc++: Add c++2a <syncstream>

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.
This commit is contained in:
Thomas Rodgers 2020-11-02 10:06:06 -08:00
parent d6912d9b17
commit 6bcbcea058
15 changed files with 939 additions and 1 deletions

View file

@ -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 \

View file

@ -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 \

View file

@ -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 \

View file

@ -141,6 +141,6 @@
#include <ranges>
#include <span>
#include <stop_token>
// #include <syncstream>
#include <syncstream>
#include <version>
#endif

View file

@ -0,0 +1,333 @@
// <syncstream> -*- C++ -*-
// Copyright (C) 2020 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
/** @file include/syncstream
* This is a Standard C++ Library header.
*/
#ifndef _GLIBCXX_SYNCSTREAM
#define _GLIBCXX_SYNCSTREAM 1
#if __cplusplus > 201703L
#include <bits/c++config.h>
#if _GLIBCXX_USE_CXX11_ABI
#define __cpp_lib_syncbuf 201803L
#pragma GCC system_header
#include <sstream>
#include <bits/alloc_traits.h>
#include <bits/allocator.h>
#include <bits/functexcept.h>
#include <bits/functional_hash.h>
#if _GLIBCXX_HAS_GTHREADS
# include <bits/std_mutex.h>
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _CharT, typename _Traits = char_traits<_CharT>,
typename _Alloc = allocator<_CharT>>
class basic_syncbuf : public basic_streambuf<_CharT, _Traits>
{
public:
using char_type = _CharT;
using int_type = typename _Traits::int_type;
using pos_type = typename _Traits::pos_type;
using off_type = typename _Traits::off_type;
using traits_type = _Traits;
using allocator_type = _Alloc;
using streambuf_type = basic_streambuf<_CharT, _Traits>;
basic_syncbuf()
: basic_syncbuf(nullptr, allocator_type{})
{ }
explicit
basic_syncbuf(streambuf_type* __obuf)
: basic_syncbuf(__obuf, allocator_type{})
{ }
basic_syncbuf(streambuf_type* __obuf, const allocator_type& __alloc)
: _M_wrapped(__obuf)
, _M_impl(__alloc)
, _M_mtx(__obuf)
{ }
basic_syncbuf(basic_syncbuf&& __other)
: _M_wrapped(__other._M_wrapped)
, _M_impl(std::move(__other._M_impl))
, _M_mtx(std::move(__other._M_mtx))
, _M_emit_on_sync(__other._M_emit_on_sync)
, _M_needs_sync(__other._M_needs_sync)
{
__other._M_wrapped = nullptr;
}
~basic_syncbuf()
{
__try
{
emit();
}
__catch (...)
{ }
}
basic_syncbuf& operator=(basic_syncbuf&& __other)
{
if (std::__addressof(__other) != this)
{
emit();
_M_impl = std::move(__other._M_impl);
_M_wrapped = __other._M_wrapped; __other._M_wrapped = nullptr;
_M_mtx = std::move(__other._M_mtx);
_M_emit_on_sync = __other._M_emit_on_sync;
_M_needs_sync = __other._M_needs_sync;
}
return *this;
}
void
swap(basic_syncbuf& __other)
{
if (std::__addressof(__other) != this)
{
std::swap(_M_impl, __other._M_impl);
std::swap(_M_wrapped, __other._M_wrapped);
std::swap(_M_mtx, __other._M_mtx);
std::swap(_M_emit_on_sync, __other._M_emit_on_sync);
std::swap(_M_needs_sync, __other._M_needs_sync);
}
}
bool
emit()
{
if (!_M_wrapped)
return false;
auto __s = _M_impl.view();
if (__s.empty())
return true;
const lock_guard<__mutex> __l(_M_mtx);
if (_M_wrapped->sputn(__s.data(), __s.size()) != __s.size())
return false;
if (_M_needs_sync)
{
_M_needs_sync = false;
if (_M_wrapped->pubsync() != 0)
return false;
}
_M_impl.str("");
return true;
}
streambuf_type*
get_wrapped() const noexcept
{ return _M_wrapped; }
allocator_type get_allocator() const noexcept
{ return _M_impl.get_allocator(); }
void
set_emit_on_sync(bool __b) noexcept
{ _M_emit_on_sync = __b; }
protected:
int
sync() override
{
auto __res = _M_impl.pubsync();
if (__res == 0)
{
_M_needs_sync = true;
if (_M_emit_on_sync)
return emit() ? 0 : -1;
}
return __res;
}
streamsize
xsputn(const char_type* __s, streamsize __n) override
{ return _M_impl.sputn(__s, __n); }
private:
streambuf_type* _M_wrapped;
using __impl_type = basic_stringbuf<char_type, traits_type,
allocator_type>;
__impl_type _M_impl;
struct __mutex
{
#if _GLIBCXX_HAS_GTHREADS
mutex* _M_mtx;
__mutex(void* __t)
: _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 _CharT, typename _Traits = char_traits<_CharT>,
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<char_type, traits_type>& __os,
const allocator_type& __a)
: basic_osyncstream(__os.rdbuf(), __a)
{ this->init(std::__addressof(_M_syncbuf)); }
explicit basic_osyncstream(basic_ostream<char_type, traits_type>& __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<syncbuf_type*>(&_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 <class _CharT, class _Traits, class _Allocator>
inline void
swap(basic_syncbuf<_CharT, _Traits, _Allocator>& __x,
basic_syncbuf<_CharT, _Traits, _Allocator>& __y) noexcept
{ __x.swap(__y); }
using syncbuf = basic_syncbuf<char>;
using wsyncbuf = basic_syncbuf<wchar_t>;
using osyncstream = basic_osyncstream<char>;
using wosyncstream = basic_osyncstream<wchar_t>;
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // _GLIBCXX_USE_CXX11_ABI
#endif // C++2a
#endif /* _GLIBCXX_SYNCSTREAM */

View file

@ -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

View file

@ -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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
// { dg-require-effective-target cxx11-abi }
#include <syncstream>
#ifndef __cpp_lib_syncbuf
# error "Feature-test macro for syncbuf missing in <syncstream>"
#elif __cpp_lib_syncbuf != 201803L
# error "Feature-test macro for syncbuf has wrong value in <syncstream>"
#endif

View file

@ -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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
// { dg-require-effective-target cxx11-abi }
#include <version>
#ifndef __cpp_lib_syncbuf
# error "Feature-test macro for syncbuf missing in <version>"
#elif __cpp_lib_syncbuf != 201803L
# error "Feature-test macro for syncbuf has wrong value in <version>"
#endif

View file

@ -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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-additional-options "-pthread" { target pthread } }
// { dg-do run { target c++2a } }
// { dg-require-effective-target cxx11-abi }
#include <sstream>
#include <string_view>
#include <syncstream>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h>
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<char>;
using sbuf_t = std::basic_syncbuf<char, std::char_traits<char>,
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;
}

View file

@ -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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
// { dg-require-effective-target cxx11-abi }
#include <syncstream>
template<typename T>
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<std::osyncstream>;
using wtest_type = type_reqs<std::wosyncstream>;
}

View file

@ -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
// <http://www.gnu.org/licenses/>.
// { 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 <algorithm>
#include <atomic>
#include <chrono>
#include <sstream>
#include <string>
#include <string_view>
#include <syncstream>
#include <thread>
#include <vector>
#include <unordered_map>
#include <utility>
#include <testsuite_hooks.h>
int
main()
{
using namespace std::chrono_literals;
std::stringbuf b;
std::atomic<unsigned> 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<std::thread> 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<std::string, int> 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<std::string_view> 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;
}

View file

@ -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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
// { dg-require-effective-target cxx11-abi }
#include <syncstream>
#ifndef __cpp_lib_syncbuf
# error "Feature-test macro for syncbuf missing in <syncstream>"
#elif __cpp_lib_syncbuf != 201803L
# error "Feature-test macro for syncbuf has wrong value in <syncstream>"
#endif

View file

@ -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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
// { dg-require-effective-target cxx11-abi }
#include <version>
#ifndef __cpp_lib_syncbuf
# error "Feature-test macro for syncbuf missing in <version>"
#elif __cpp_lib_syncbuf != 201803L
# error "Feature-test macro for syncbuf has wrong value in <version>"
#endif

View file

@ -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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-additional-options "-pthread" { target pthread } }
// { dg-do run { target c++2a } }
// { dg-require-effective-target cxx11-abi }
#include <sstream>
#include <string_view>
#include <syncstream>
#include <testsuite_allocator.h>
#include <testsuite_hooks.h>
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<char>;
using sbuf_t = std::basic_syncbuf<char, std::char_traits<char>,
alloc_type>;
using stream_t = std::basic_osyncstream<char, std::char_traits<char>,
alloc_type>;
using str_t = std::basic_ostringstream<char, std::char_traits<char>,
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;
}

View file

@ -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
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
// { dg-require-effective-target cxx11-abi }
#include <syncstream>
template<typename T>
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<std::osyncstream>;
using wtest_type = type_reqs<std::wosyncstream>;
}