在给定阻塞的情况下,在服务器上下文中读取C ++ 11流的正确方法是什么?

时间:2019-02-19 18:36:16

标签: c++ c++11 asynchronous io

鉴于所有标准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 ++ 11解决此问题?不可能吗?

当然有非标准解决方案,但是可以单独用C ++做到吗?

0 个答案:

没有答案