鉴于所有标准C ++ 11流读取均处于阻塞状态,在服务上下文中读取C ++流的正确方法是什么?我曾尝试将阻塞读取放置在线程中,但是当我尝试加入线程时,只是再次遇到了阻塞。
我有一个用输入流实例化的类Reader,它可能是无穷的(EOF)。
阅读器可能会启动(非阻塞),这时阅读器会启动一个线程,该线程逐行读取流,对每行执行某项操作,直到内部 ,发生错误或达到EOF,或者外部,调用Reader的stop方法。
Reader的stop方法必须加入线程,但是如果线程在读取时被阻止,则该加入将阻塞!析构函数也是如此。
#include <iostream>
#include <thread>
#include <mutex>
#include <assert.h>
enum State {
PRE, STARTED, STOPPED
};
class Reader {
std::istream& source;
State state { PRE };
std::mutex mutex { };
std::thread* myThread { nullptr };
bool eof {false};
bool error {false};
public:
Reader(std::istream& source) :
source(source) {
}
~Reader() {
if (myThread!=nullptr) {
myThread->join();
}
delete myThread;
}
void start() {
using namespace std;
mutex.lock();
if (state != PRE)
throw -1;
state = STARTED;
myThread = new std::thread { [&]() {
while(state==STARTED) {
string line {};
getline(source, line);
if (source.eof()) {
mutex.lock();
state=STOPPED; // internal stop
eof=true;
mutex.unlock();
break;
}
if (!source.good()) {
mutex.lock();
state=STOPPED; // internal stop
error=true;
mutex.unlock();
break;
}
if (state==STARTED) { // may have been stopped externally
// do something important
cout << "'"<<line<<"'"<<endl;
}
}
}
};
mutex.unlock();
}
void stop() {
mutex.lock();
if (state != STARTED)
throw -2;
state = STOPPED;
myThread->join();
delete myThread;
myThread=nullptr;
mutex.unlock();
}
bool isStarted() const {
return state==STARTED;
}
bool isStopped() const {
return state==STOPPED;
}
bool isEof() const {
return eof;
}
bool isError() const {
return error;
}
};
int main() {
using namespace std;
Reader r { cin };
r.start();
cout << "[SLEEPING]..." << endl;
this_thread::sleep_for(chrono::seconds(6));
cout << "...[AWAKE]" << endl;
cout << "[EOF:"<<to_string(r.isEof())<<"]" << endl;
cout << "[ERROR:"<<to_string(r.isError())<<"]" << endl;
cout << "[STILL STARTED:"<<to_string(r.isStarted())<<"]" << endl;
if (r.isStarted()) {
cout << "[STOPPING]..." << endl;
r.stop();
cout << "...[STOPPED]" << endl;
}
cout << "[EXIT]" << endl;
return 0;
}
主要功能演示了该问题。 Reader使用std :: cin实例化并启动。然后主线程会睡一会儿。
当主线程醒来时,它将检查阅读器是否仍在启动((除非遇到错误或EOF才会启动))。如果阅读器仍启动(在这种情况下,线程在读取时被阻塞),我们将停止阅读器。
如果您运行代码(与pthread链接),并在睡眠期间按Ctrl-D,则所有(当然是在睡眠之后)都会正确终止。 >
但是如果您等待睡眠时间,程序将停止停止,并且永远不会退出。
当然有非标准解决方案,但是可以单独用C ++做到吗?