我已经发现另一个问题,Windows / MingW没有提供过时的usleep()的nanosleep()和setitimer()替代品。 但我的目标是修复cppcheck给我的所有警告,包括usleep()样式警告。
那么,是否有一种解决方法以某种方式避免使用cygwin或安装大量新依赖项/库的Windows 上的usleep()?感谢。
答案 0 :(得分:44)
我使用了此代码(最初来自here):
#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编译器,那么你可以使用this便携版:
#include <chrono>
#include <thread>
...
std::this_thread::sleep_for(std::chrono::microseconds(usec));
感谢Howard Hinnant设计了令人惊叹的<chrono>
图书馆(和whose answer below值得更多的爱。)
如果你没有C ++ 11,但是你有提升,那么你可以改为this:
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
...
boost::this_thread::sleep(boost::posix_time::microseconds(usec));
答案 1 :(得分:10)
旧问题的新答案:
新答案的基本原理:工具/操作系统已经更新,现在有一个比最初提出问题时更好的选择。
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的早期版本。
答案 2 :(得分:8)
Sleep()
函数的毫秒范围很好地描述并且很好理解。它没有做任何不可预测的事情。有时,该功能被指责为执行不可预测的,即在延迟到期之前返回。我需要说这是错的。仔细调查将证实其行为是绝对可预测的。唯一的问题是
有很多东西可以阅读它,其中大部分都是带小孩的。人们也经常这样说
Windows它不是一个实时操作系统。但是这样的评论并没有贡献任何东西,而且这样做
评论用于隐藏缺乏知识。这让我有点生气,甚至没有
微软注意到了这一点并提供了更好的文档。
然而,不夸大这个小答案:sleep()函数是精确的,当以正确的方式使用并且知道它的特征时。必须特别注意睡眠(0)。这是一个非常强大的工具,特别是与进程优先级,线程优先级,多媒体计时器设置和处理器关联掩码一起使用时。
因此,通常可以在系统中断期间轻松安全地执行真正的睡眠。当睡眠时间比中断时间短时,需要旋转。
必须在奥德中使用更高分辨率的时间源以在更短的时间内旋转。
最常见的来源是性能计数器。 QueryPerformanceCounter(*arg)
提供递增* arg。 QueryPerformanceFrequency(*arg)
提供性能计数器递增的频率。这通常在MHz范围内,并且根据底层硬件而变化。 MHz范围内的频率提供微秒分辨率。这样,可以使用高分辨率的某些东西来等待期望的时间跨度到期。但是,必须仔细查看其准确性:OS将性能计数器频率作为常量返回。这是错的!由于生成的频率是物理设备,因此始终存在偏移,也不是a
不变。它有热漂移。更现代的系统确实具有较少的漂移。但如果热漂移仅为1ppm,则误差将为1us / s。偏移可以很容易地为几个100.在1MHz中100的偏移对应于100us / s。
如果一个线程要以高分辨率等待任何时间,它应该建立一个服务线程。两个线程都应共享一个命名事件。服务线程应在所需的睡眠延迟之前休眠1个中断周期,然后在性能计数器上旋转剩余的微秒。当服务线程到达最后时间时,它设置命名事件并结束。调用线程将被唤醒,因为它正在通过等待函数等待命名事件。
要点:
答案 3 :(得分:4)
我找到了this blog post about it。它使用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);
}
我希望这有点帮助。
答案 4 :(得分:4)
这取决于您需要的粒度。如果您正在谈论毫秒,那么Win32 Sleep功能将完成这项工作 - 请参阅http://msdn.microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx。如果你正在谈论微秒,那么没有简单的方法可以做到这一点,你很幸运能够在Windows(不是RTOS)或Linux上获得那种计时器分辨率。
答案 5 :(得分:0)
我参加聚会很晚,但是我想在这个问题上添加一些内容。如果要使用微秒分辨率实现可移植性,而不是使用select()
系统调用(使用空文件描述符集)来实现可移植性。它可以在linux和Windows上运行,即可以使用统一的界面来调用它(行为可能仍然不同,尤其是在Windows上,您可以请求1微秒但睡眠1毫秒)。如果要使用第三方库,请使用Boost,但要使用最新版本。与时间相关的std api只是一团糟,我在此处提供摘要:
因此,如果您要使用可移植的代码编写自己的解决方案或仅使用Boost 1.67+,请不要信任标准实现c ++ 11 chrono,因为执行的实现确实很糟糕。
答案 6 :(得分:-3)
usleep()
适用于微秒。在获得微秒精度的窗口中,您应该使用QueryPerformanceCounter() winapi函数。 Here你可以找到如何使用它获得精确度。