c ++,usleep()已经过时,Windows / MingW的解决方法?

我已经发现另一个问题,Windows / MingW没有提供过时的usleep()的nanosleep()和setitimer()方法。 但我的目标是解决cppcheck给我的所有警告,包括usleep()样式警告。

那么,有没有一种解决方法,以避免使用cygwin或安装大量的新的依赖关系/库的Windows上的usleep()? 谢谢。

usleep()与微秒一起工作。 在获取微秒的视窗中,您应该使用QueryPerformanceCounter() winapi函数。 在这里你可以找到如何使用它来获得这个领域。

我用这个代码(最初来自这里 ):

 #include <windows.h> void usleep(__int64 usec) { HANDLE timer; LARGE_INTEGER ft; ft.QuadPart = -(10*usec); // Convert to 100 nanosecond interval, negative value indicates relative time timer = CreateWaitableTimer(NULL, TRUE, NULL); SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); WaitForSingleObject(timer, INFINITE); CloseHandle(timer); } 

请注意, SetWaitableTimer()使用“ 100纳秒间隔…正值表示绝对时间…负值表示相对时间 ”,并且“ 实际的计时器精度取决于您的硬件的能力 ”。

如果你有一个C ++ 11编译器,那么你可以使用这个便携版本:

 #include <chrono> #include <thread> ... std::this_thread::sleep_for(std::chrono::microseconds(usec)); 

如果你没有C ++ 11,但你有提升,那么你可以这样做:

 #include <boost/thread/thread.hpp> #include <boost/date_time/posix_time/posix_time.hpp> ... boost::this_thread::sleep(boost::posix_time::microseconds(usec)); 

Sleep()函数的毫秒范围是很好的描述和很好的理解。 它不会做任何不可预测的事情。 有时候这个功能被指责为执行不可预知的,即在延迟过期之前返回。 我需要说这是错误的。 仔细的调查将证实其行为是绝对可预测的。 唯一的问题就是有很多东西需要阅读,而且大部分是kiddish。 也经常说,它不是一个实时的操作系统。 但是这样的评论没有什么贡献,而且这样的评论被用来掩盖知识的缺乏。 这让我有点生气,甚至微软也没有注意到这一点,并提供更好的文档。

但是,不要夸大这个小小的回答:当sleep()函数以正确的方式使用,并且知道它的特性时,它是精确的。 必须特别注意睡眠(0)。 这是一个非常强大的工具,特别是与进程优先级,线程优先级,多媒体计时器设置和处理器关联掩码一起使用时。

所以一般来说,真正的睡眠可以轻松安全地进行到系统中断期。 在睡眠时间比中断时间要短的情况下。 必须使用更高分辨率的时间源才能在较短的时间内旋转。 最常见的来源是性能计数器。 QueryPerformanceCounter(*arg)递增* arg。 QueryPerformanceFrequency(*arg)提供性能计数器递增的频率。 这通常是在MHz制度,并根据底层硬件而有所不同。 MHz范围内的频率提供了微秒的分辨率。 这样,高分辨率的东西可以用来等待期望的时间跨度到期。 但是,必须仔细查看其准确性:OS将性能计数器频率作为常数返回。 这是错误的! 由于频率是一个物理设备,总是有一个偏移量,它也不是一个常数。 它有热漂移。 更现代的系统的漂移少。 但是,如果热漂移只有1ppm,误差将是1us / s。 偏移可以轻松地为几百个。在1MHz的偏移100对应于100us / s。

如果一个线程以高分辨率等待任何时间,它应该建立一个服务线程。 这两个线程应共享一个命名的事件。 服务线程应睡眠到所需睡眠延迟之前的1个中断周期,然后在性能计数器上旋转剩余的微秒。 当服务线程到达最后时间时,它设置指定的事件并结束。 调用线程将被唤醒,因为它正在通过等待函数等待指定的事件。

概要:

  • 睡眠很好理解但记录不完整。
  • 服务线程可以模仿高分辨率的睡眠。
  • 这样的服务线程可以作为系统级的服务来建立。
  • 性能计数器的准确性要仔细考虑。 校准是必需的。

更详细的信息可以在Windows时间戳项目中找到

一个老问题的新答案:

新答案的理由:工具/操作系统已经更新,因此现在有一个更好的选择,而不是最初提出问题的时候。

现在C ++ 11 <chrono><thread> std头文件已经在VS工具集中。 使用这些头文件,最好在C ++ 11中编码为:

 std::this_thread::sleep_for(std::chrono::microseconds(123)); 

我仅以微秒作为示例持续时间。 你可以使用任何方便的时间:

 std::this_thread::sleep_for(std::chrono::minutes(2)); 

有了C ++ 14和一些使用指令,这可以写得更紧凑一些:

 using namespace std::literals; std::this_thread::sleep_for(2min); 

要么:

 std::this_thread::sleep_for(123us); 

这绝对适用于VS-2013(模拟计时文字)。 我不确定VS的早期版本。

这取决于你需要的粒度。 如果您正在讲毫秒,那么Win32睡眠功能将完成这项工作 – 请参阅http://msdn.microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx 如果你正在谈论微秒,那么就没有简单的方法去做,而且在Windows(不是RTOS)或者Linux上得到这种定时器分辨率是很幸运的。

我发现这个博客文章 。 它使用QueryPerformanceCounter 发布的功能:

 #include <windows.h> void uSleep(int waitTime) { __int64 time1 = 0, time2 = 0, freq = 0; QueryPerformanceCounter((LARGE_INTEGER *) &time1); QueryPerformanceFrequency((LARGE_INTEGER *)&freq); do { QueryPerformanceCounter((LARGE_INTEGER *) &time2); } while((time2-time1) < waitTime); } 

我希望这个能有一点帮助。