質問

I'm trying to build a thread that checks for user input and if the input equals "exit", it turns off all other threads.

The way that I use cin seems to stop the thread. The thread should run, check for user input, and if there is any and it equals "exit", turn runProcesses off.

This is my code that doesn't work as expected as "newline stopped" never is printed, "running" is printed only once:

void check_for_cin() {
    while ( runProcesses ) {
        cout << "running";
        string input;
        std::getline( std::cin, input );
        //while ( std::getline( std::cin, input ) ) {
        if ( !input.empty() ) {
            if ( input == "exit" ) {
                runProcesses = false;
                cout << "exiting" << ", run processes: " << runProcesses;
            }
        }
        cout << "newline stopped";
        boost::this_thread::sleep( boost::posix_time::seconds( 1 ) );
    }
    cout << "no longer checking for input";
}

How can my intent be done?

役に立ちましたか?

解決

Look at Asio's file descriptor service objects.

Posix has a 'reactor' style asynchrony, so you don't actually need threads to achieve asynchronicity.

My example shows a reading loop that exits when 'exit' is typed /or/ when a timeout expires (10s).

#include <boost/asio.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>

boost::asio::io_service my_io_service;
boost::asio::posix::stream_descriptor in(my_io_service, ::dup(STDIN_FILENO));
boost::asio::deadline_timer timer(my_io_service);

// handle timeout
void timeout_expired(boost::system::error_code ec) {
    if (!ec)
        std::cerr << "Timeout expired\n";
    else if (ec == boost::asio::error::operation_aborted) // this error is reported on timer.cancel()
        std::cerr << "Leaving early :)\n";
    else 
        std::cerr << "Exiting for another reason: " << ec.message() << "\n";

    // stop the reading loop
    in.cancel();
    in.close();
}

// set timeout timer
void arm_timeout()
{
    timer.expires_from_now(boost::posix_time::seconds(10));
    timer.async_wait(timeout_expired);
}

// perform reading loop
void reading_loop()
{
    std::cerr << "(continueing input...)\n";
    static boost::asio::streambuf buffer; // todo some encapsulation :)

    async_read_until(in, buffer, '\n', [&](boost::system::error_code ec, size_t bytes_transferred) {
            if (!ec)
            {
                std::string line;
                std::istream is(&buffer);
                if (std::getline(is, line) && line == "exit")
                    ec = boost::asio::error::operation_aborted;
                else
                    reading_loop(); // continue
            } 

            if (ec)
            {
                std::cerr << "Exiting due to: " << ec.message() << "\n";
                // in this case, we don't want to wait until the timeout expires
                timer.cancel();
            }
    });
}

int main() {

    arm_timeout();
    reading_loop();

    my_io_service.run();
}

On windows, you can use the equivalent Windows Stream Handle

You could trivially add threads by running my_io_service.run() on more than one thread.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top