2015-12-22 71 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來掛鉤其狀態轉換,並在狀態更改時執行任何您需要的操作。一種可能性是使用電源管理器線程註冊所有條件變量,該線程在機器從睡眠狀態恢復時對每個已註冊的條件變量執行喚醒。

相關問題