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 可以做到。

https://godbolt.org/z/fs9TGW

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;
}