我有一个与此类似的问题:
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/
上它说
它的行为就像实现为: return wait_until(lck,chrono :: steady_clock :: now()+ rel_time,std :: move(pred));
输出显示即使在PC处于睡眠状态时,steady_clock也会前进 问题:为什么condition_variable :: wait_until只计算PC唤醒时的持续时间?
答案 0 :(得分:2)
没有一个完美的解决方案适合所有情况,但这是你大多数时候都想要的,并且它需要最少的烦恼才能让它以不同的方式工作。如果它根据墙壁时间工作,那么如果机器处于睡眠状态,当它重新醒来时,一切都会立即唤醒,不仅弄乱了每次睡眠的绝对时间,还弄乱了它们之间的相对时间。
如果您关心,请使用操作系统的电源管理API来挂接其状态转换,并在状态发生变化时执行您需要的任何操作。一种可能性是使用电源管理器线程注册所有条件变量,该线程在机器从睡眠状态恢复时对每个已注册的条件变量进行唤醒。