如何从另一个线程停止std :: cin再读取输入?

时间:2017-02-22 15:32:14

标签: c++ multithreading c++11 cin

我启动了两个主题,thread t1正在等待cin的输入。我可以将EOF位之类的内容从cin thread t2添加到cin以阻止'\n'阅读吗?我尝试了ios::eofbit#include <thread> #include <iostream> #include <string> #include <condition_variable> std::condition_variable cv; void Foo() { std::string sFoo; std::cin >> sFoo; // Do stuff with sFoo } void Bar() { // Do stuff // If a condition is fullfilled I don't need the input in Foo anymore and so I want to cancel cin. std::cin.setstate(std::ios::setstate(std::ios::eofbit); // Does not work std::cin.putback('\n'); // Does not work // maybe something similar like these above } int main() { std::thread t1(Foo); std::thread t2(Bar); } 。两者都不起作用。

{{1}}

1 个答案:

答案 0 :(得分:0)

我不认为有来自istream的标准非阻塞读取或中断等待输入的线程的方法。您可能会尝试查看boost asio或增强iostreams - 也许他们有这个功能。

您可以在POSIX系统或其他系统上的对应系统上使用select / poll来检查是否有任何数据可用,或者使用某种形式的中断读取 - API也是系统相关的。

下面是一个有效的脏解决方案 - 你最终会得到一个泄漏的线程,它将永远等待stdin,但它会做你想要的。

#include <thread>
#include <iostream>
#include <string>
#include <condition_variable>
#include <chrono>
#include <mutex>
#include <queue>

std::mutex m;
bool dataEnd = false;
std::queue<std::string> data;
std::condition_variable sAvail;

void Reader() {
    while (std::cin) {
        auto s = std::string();
        std::cin >> s;

        auto lock = std::unique_lock<std::mutex>(m);
        data.push(std::move(s));
        sAvail.notify_all();
    }
}

void Foo() {
    for (;;) {
        auto lock = std::unique_lock<std::mutex>(m);
        if (data.empty()) {
            sAvail.wait(lock);
            if (dataEnd) {
                std::cerr << "No more data!\n";
                break;
            }
        }

        if (!data.empty()) {
            auto s = std::move(data.front());
            data.pop();
            std::cerr << "Got " << s << '\n';
        }
    }
}

void Bar(std::thread& reader) {
    // Do stuff
    // If a condition is fullfilled I don't need the input in Foo anymore and so I want to cancel cin.

    {
        auto lock = std::unique_lock<std::mutex>(m);
        dataEnd = true;
        sAvail.notify_all();
        reader.detach();
    }

    // maybe something similar like these above
}

int main() {
    std::thread r(Reader);
    std::thread t1(Foo);
    std::this_thread::sleep_for(std::chrono::milliseconds(5000));
    std::thread t2(Bar, std::ref(r));

    t1.join();
    t2.join();
}