std::stringstream 跨线程未按预期工作
std::stringstream across threads doesn't work as expected
我正在使用 std::iostreams
在线程之间发送流数据,但很难提取数据,这是一个人为的例子:
#include <sstream>
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>
using namespace std::chrono_literals;
int main()
{
auto stream = std::stringstream{};
auto stop = std::atomic_bool{false};
auto mtx = std::mutex{};
auto thread = std::thread{[&]() {
while(!stop) {
auto lock = std::lock_guard{mtx};
if (stream.peek() != decltype(stream)::traits_type::eof()) {
auto str = std::string{};
stream >> str;
std::cout << str;
}
}
}};
{
// Make sure thread is running before sending data
std::this_thread::sleep_for(100ms);
{
auto lock = std::lock_guard{mtx};
stream << "hello" << std::endl;
}
// Give the thread a chance to receive it
std::this_thread::sleep_for(100ms);
}
stop = true;
thread.join();
return EXIT_SUCCESS;
}
Running it,没有输出 - 调试显示 stream.peek()
总是 EOF
。我一定是做错了什么,但我看不到!
问题是由于您在有任何可读内容(已写入)之前读取数据造成的。
当您尝试从空流中读取数据时,系统会设置错误标志,然后在清除错误标志之前不会执行对此类流的任何后续 read/write 操作。
您需要一些能够确保在写入之后进行读取的东西。 std::condition_variable
可以做到。
int main()
{
auto stream = std::stringstream{};
auto mtx = std::mutex{};
auto hasData = std::condition_variable{};
auto readingStarted = std::condition_variable{};
auto thread = std::thread{[&]() {
std::unique_lock<std::mutex> lock{mtx};
readingStarted.notify_one();
hasData.wait(lock);
auto str = std::string{};
stream >> str;
std::cout << str;
}};
{
auto lock = std::unique_lock{mtx};
readingStarted.wait(lock);
stream << "hello" << std::endl;
hasData.notify_one();
}
thread.join();
return EXIT_SUCCESS;
}
我正在使用 std::iostreams
在线程之间发送流数据,但很难提取数据,这是一个人为的例子:
#include <sstream>
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <mutex>
using namespace std::chrono_literals;
int main()
{
auto stream = std::stringstream{};
auto stop = std::atomic_bool{false};
auto mtx = std::mutex{};
auto thread = std::thread{[&]() {
while(!stop) {
auto lock = std::lock_guard{mtx};
if (stream.peek() != decltype(stream)::traits_type::eof()) {
auto str = std::string{};
stream >> str;
std::cout << str;
}
}
}};
{
// Make sure thread is running before sending data
std::this_thread::sleep_for(100ms);
{
auto lock = std::lock_guard{mtx};
stream << "hello" << std::endl;
}
// Give the thread a chance to receive it
std::this_thread::sleep_for(100ms);
}
stop = true;
thread.join();
return EXIT_SUCCESS;
}
Running it,没有输出 - 调试显示 stream.peek()
总是 EOF
。我一定是做错了什么,但我看不到!
问题是由于您在有任何可读内容(已写入)之前读取数据造成的。
当您尝试从空流中读取数据时,系统会设置错误标志,然后在清除错误标志之前不会执行对此类流的任何后续 read/write 操作。
您需要一些能够确保在写入之后进行读取的东西。 std::condition_variable
可以做到。
int main()
{
auto stream = std::stringstream{};
auto mtx = std::mutex{};
auto hasData = std::condition_variable{};
auto readingStarted = std::condition_variable{};
auto thread = std::thread{[&]() {
std::unique_lock<std::mutex> lock{mtx};
readingStarted.notify_one();
hasData.wait(lock);
auto str = std::string{};
stream >> str;
std::cout << str;
}};
{
auto lock = std::unique_lock{mtx};
readingStarted.wait(lock);
stream << "hello" << std::endl;
hasData.notify_one();
}
thread.join();
return EXIT_SUCCESS;
}