I don't think there is a standard non-blocking read from istream or a means to interrupt a thread waiting for input. You might try to look at boost asio or boost iostreams - perhaps they have this functionality.
You could use select/poll on POSIX systems or their counterparts on other systems to check if any data is available, or use some form of interruptive read - API is system-dependent also.
Below is a dirty solution that works - you end up with a leaked thread that will forever wait on stdin, but it does what you want.
#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();
}