Does non-blocking read from std::cin work with std::this_thread::sleep_for() or std::this_thread::yield() (IPC)

前端 未结 1 1045
执笔经年
执笔经年 2021-01-25 03:18

I\'ve encountered a specific problem with my implementation and can\'t find a solution for it.

I have a two-part application. One part is a Java swing GUI. The second pa

相关标签:
1条回答
  • 2021-01-25 03:44

    After trying for a long time to implement non-blocking input from cin, I'm pretty sure it's impossible to getting it to work consistently.

    My current solution is to put the blocking cin into it's own tiny thread and let it do it's thing.

    I've simplified my implementation a little bit for this example, as you need a thread safe storage system of some kind.

    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <queue>
    
    // Super simple thread safe storage
    std::queue<std::string> Database;
    std::mutex Padlock;
    void PushLine(std::string Line) {
        std::unique_lock<std::mutex> Lock(Padlock); (void)Lock;
        Database.push(Line);
    }
    bool IsLineAvailable(void) {
        std::unique_lock<std::mutex> Lock(Padlock); (void)Lock;
        return !Database.empty();
    }
    std::string PopLine(void) {
        std::unique_lock<std::mutex> Lock(Padlock); (void)Lock;
        std::string Line(std::move(Database.front()));
        Database.pop();
        return Line;
    }
    
    // Main function with "non-blocking" input from cin
    int main(int argc, char *argv[]) {
        (void)argc;
        (void)argv;
        std::thread InputThread = std::thread([](){
            do {
                // Ensure the input is as clean as possible
                if (std::cin.rdbuf()->in_avail()) {
                    std::cin.ignore(std::cin.rdbuf()->in_avail());
                }
                std::cin.clear();
    
                // Get a line, cin will block here.
                std::string Line;
                std::getline(std::cin, Line);
    
                // If the line is not empty attempt to store it.
                if (!Line.empty()) {
                    PushLine(Line);
                }
            } while (1);
        });
    
        // Detach from the thread, it will never end.
        InputThread.detach();
    
        // A job to do.
        unsigned int Counter = 0;
    
        // Run your program.
        bool Running = true;
        while(Running) {
            // Perform a job, in this case counting.
            Counter++;
    
            // Check for available input
            if (IsLineAvailable()) {
                // If there is input available, first get it
                std::string Line = PopLine();
    
                // Echo it to the terminal
                std::cout << "Command: " << Line << std::endl;
    
                // Perform actions based on the command
                if (Line == "quit") {
                    Running = false;
                }
                else if (Line == "count") {
                    std::cout << "  Count: " << Counter << std::endl;
                }
            }
    
            // Sleep for a while
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    
        // Done.
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题