2015-12-22 36 views
0

我有类似这样的一个问题:condition_variable :: wait_for和wait_until使用chrono :: steady_clock但在PC休眠时跳过持续时间?

Are there any STL functions that wait that use wallclock time instead of "machine awake" time?

我写了下面一个简单的测试程序。其输出作为main()函数之后的注释附加。

#include <iostream> 
#include <atomic> 
#include <condition_variable> 
#include <thread> 
#include <chrono> 

namespace Test1 { 
    std::condition_variable cv1; 
    std::mutex cv_m1; 
    std::atomic<int> i1{ 0 }; 

    void WaitForTest(int durationSeconds) 
    { 
     std::unique_lock<std::mutex> lk(cv_m1); 
     if (cv1.wait_for(lk, std::chrono::seconds(durationSeconds), []() {return i1 > 0;})) 
      std::cerr << "Thread WaitForTest finished waiting. i == " << i1 << '\n'; 
     else 
      std::cerr << "Thread WaitForTest timed out. i == " << i1 << '\n'; 
    } 
} 

namespace Test2 { 
    std::condition_variable cv1; 
    std::mutex cv_m1; 
    std::atomic<int> i1{ 0 }; 

    void WaitUntilTest(int durationSeconds) 
    { 
     std::unique_lock<std::mutex> lk(cv_m1); 
     if (cv1.wait_until(lk, std::chrono::steady_clock::now() + std::chrono::seconds(durationSeconds), []() {return i1 > 0;})) 
      std::cerr << "Thread WaitUntilTest finished waiting. i == " << i1 << '\n'; 
     else 
      std::cerr << "Thread WaitUntilTest timed out. i == " << i1 << '\n'; 
    } 
} 

void DisplayCounter() 
{ 
    for (;;) 
    { 
     std::cout << std::chrono::steady_clock::now().time_since_epoch().count() << '\t'; 
     std::cout << std::chrono::system_clock::now().time_since_epoch().count() << std::endl; 
     std::this_thread::sleep_for(std::chrono::seconds(1)); 
    } 
} 

int main() 
{ 
    std::thread t0(DisplayCounter); 
    std::thread t1(Test1::WaitForTest, 20); 
    std::thread t2(Test2::WaitUntilTest, 20); 
    t1.join(); 
    t2.join(); 
    t0.join(); 
} 

/* 
4823241754127 14507388260401666 
4824249305761 14507388270471228 
4825256111840 14507388280536768 
4826265075762 14507388290623794 
4827272062892 14507388300690885 
4828278976945 14507388310756954 
4829285939442 14507388320824912 
4830292731972 14507388330889902 
4831301325579 14507388340950061 
4832325019583 14507388351168172 
4833328913228 14507388361252847 
4834344668038 14507388371893418 
4835526960329 14507388383183227 // Put PC to sleep for several minutes here. 
5239334902724 14507392428113950 
5241228987291 14507392440270719 
5242391680803 14507392453061650 
5243860130948 14507392467439058 
5245178576003 14507392479499693 
Thread WaitUntilTest timed out. i == 5246249606694Thread WaitForTest timed out. i == 14507392493628356 
0 
0 
5247878128997 14507392507329527 
5249076101379 14507392518267779 
5250080155548 14507392528308436 
*/ 

/* 
6901440131309 14507409048031904 
6902447235446 14507409058098709 
6903453988153 14507409068147687 
6904456435024 14507409078169356 
6905459314613 14507409088221283 
6906465590262 14507409098284729 
6907472642259 14507409108354858 
6908479366227 14507409118421845 
6909485420590 14507409128482293 
6910492000867 14507409138524952 
6911494460464 14507409148547279 
6912496188054 14507409158571820 
6913503297528 14507409168712603 
6914518360974 14507409178777637 
6915520958927 14507409188797529 
6916522928740 14507409273645140 // Put PC to sleep for several seconds here. 
6925151268349 14507409284698259 
6926154791268 14507409294728122 
6927189995828 14507409306269589Thread WaitForTest timed out. i == 
Thread WaitUntilTest timed out. i == 0 
0 
6928477053195 14507409318749386 
6929719714225 14507409331272114 
6930891244389 14507409342498796 
*/ 

在网页http://www.cplusplus.com/reference/condition_variable/condition_variable/wait_for/

它说

它的行为就好像是执行: 回报wait_until(LCK,计时:: steady_clock ::现在()+ REL_TIME,标准: :移动(预解码值));

输出显示,即使PC睡着了,steady_clock也会提前。
问:为什么condition_variable :: wait_until只计算PC唤醒时的持续时间?

回答

2

没有一种适用于所有情况的完美解决方案,但这是您大多数时间需要的,并且它需要最少的努力才能让它以不同的方式工作。如果它是以墙上时间为基础的,那么如果机器睡着了,当它醒来时,一切都会一下子醒来,不仅是每次睡眠的绝对时间,还有它们之间的相对时间。

如果您在意,请使用操作系统的电源管理API来挂钩其状态转换,并在状态更改时执行任何您需要的操作。一种可能性是使用电源管理器线程注册所有条件变量,该线程在机器从睡眠状态恢复时对每个已注册的条件变量执行唤醒。

相关问题