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:
parent
d6912d9b17
commit
6bcbcea058
15 changed files with 939 additions and 1 deletions
|
@ -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 \
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -141,6 +141,6 @@
|
|||
#include <ranges>
|
||||
#include <span>
|
||||
#include <stop_token>
|
||||
// #include <syncstream>
|
||||
#include <syncstream>
|
||||
#include <version>
|
||||
#endif
|
||||
|
|
333
libstdc++-v3/include/std/syncstream
Normal file
333
libstdc++-v3/include/std/syncstream
Normal 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 */
|
|
@ -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
|
||||
|
|
28
libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc
Normal file
28
libstdc++-v3/testsuite/27_io/basic_syncbuf/1.cc
Normal 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
|
28
libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc
Normal file
28
libstdc++-v3/testsuite/27_io/basic_syncbuf/2.cc
Normal 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
|
137
libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc
Normal file
137
libstdc++-v3/testsuite/27_io/basic_syncbuf/basic_ops/1.cc
Normal 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;
|
||||
}
|
|
@ -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>;
|
||||
}
|
130
libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc
Normal file
130
libstdc++-v3/testsuite/27_io/basic_syncbuf/sync_ops/1.cc
Normal 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;
|
||||
}
|
28
libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc
Normal file
28
libstdc++-v3/testsuite/27_io/basic_syncstream/1.cc
Normal 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
|
28
libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc
Normal file
28
libstdc++-v3/testsuite/27_io/basic_syncstream/2.cc
Normal 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
|
134
libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc
Normal file
134
libstdc++-v3/testsuite/27_io/basic_syncstream/basic_ops/1.cc
Normal 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;
|
||||
}
|
|
@ -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>;
|
||||
}
|
Loading…
Add table
Reference in a new issue