why do I need std::condition_variable?

后端 未结 2 366
南方客
南方客 2020-12-07 12:30

I found that std::condition_variable is very difficult to use due to spurious wakeups. So sometimes I need to set a flags such as:

atomic

        
2条回答
  •  春和景丽
    2020-12-07 12:40

    You can code this either way:

    1. Using atomics and a polling loop.
    2. Using a condition_variable.

    I've coded it both ways for you below. On my system I can monitor in real time how much cpu any given process is using.

    First with the polling loop:

    #include 
    #include 
    #include 
    #include 
    
    std::atomic is_ready(false);
    
    void
    test()
    {
        std::this_thread::sleep_for(std::chrono::seconds(30));
        is_ready.store(true);
    }
    
    int
    main()
    {
        std::thread t(test);
        while (!is_ready.load())
            std::this_thread::yield();
        t.join();
    }
    

    For me this takes 30 seconds to execute, and while executing the process takes about 99.6% of a cpu.

    Alternatively with a condition_variable:

    #include 
    #include 
    #include 
    #include 
    #include 
    
    bool is_ready(false);
    std::mutex m;
    std::condition_variable cv;
    
    void
    test()
    {
        std::this_thread::sleep_for(std::chrono::seconds(30));
        std::unique_lock lk(m);
        is_ready = true;
        cv.notify_one();
    }
    
    int
    main()
    {
        std::thread t(test);
        std::unique_lock lk(m);
        while (!is_ready)
        {
            cv.wait(lk);
            if (!is_ready)
                std::cout << "Spurious wake up!\n";
        }
        t.join();
    }
    

    This has the exact same behavior except that during the 30 second execution, the process is taking 0.0% cpu. If you're writing an app that might execute on a battery powered device, the latter is nearly infinitely easier on the battery.

    Now admittedly, if you had a very poor implementation of std::condition_variable, it could have the same inefficiency as the polling loop. However in practice such a vendor ought to go out of business fairly quickly.

    Update

    For grins I augmented my condition_variable wait loop with a spurious wakeup detector. I ran it again, and it did not print out anything. Not one spurious wakeup. That is of course not guaranteed. But it does demonstrate what a quality implementation can achieve.

提交回复
热议问题