blob: 753a341c372854c3fb278a724ce02dc026fe8ad6 [file] [log] [blame]
// Copyright (C) 2020-2023 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 run { target c++2a } }
// { dg-require-effective-target cxx11_abi }
// { dg-require-gthreads "" }
// { dg-add-options libatomic }
// { dg-additional-options "-pthread" { target pthread } }
#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;
}