c++,usleep() 已过时,Windows/MingW 的解决方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5801813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
c++, usleep() is obsolete, workarounds for Windows/MingW?
提问by blubberbernd
I already found out with another question that Windows/MingW doesn't provide the nanosleep() and setitimer() alternatives to the obsolete usleep(). But my goal is to fix all warnings that cppcheck gives me, including the usleep() style warnings.
我已经在另一个问题中发现 Windows/MingW 没有提供 nanosleep() 和 setitimer() 替代过时的 usleep()。但我的目标是修复 cppcheck 给我的所有警告,包括 usleep() 样式警告。
So, is there a workaround to somehow avoid usleep() on Windows withoutusing cygwin or installing loads of new dependencies/libraries? Thanks.
那么,是否有一种解决方法可以在不使用 cygwin 或安装大量新依赖项/库的情况下以某种方式避免 Windows 上的 usleep() ?谢谢。
采纳答案by Mihran Hovsepyan
usleep()
works with microseconds. In windows for getting microsecond precesion you should use QueryPerformanceCounter()winapi function. Hereyou can find how get that precesion using it.
usleep()
以微秒为单位工作。在 Windows 中获取微秒精度,您应该使用QueryPerformanceCounter()winapi 函数。在这里您可以找到如何使用它来获得该进动。
回答by Adi Shavit
I used this code from (originally from 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);
}
Note that SetWaitableTimer()
uses "100 nanosecond intervals ... Positive values indicate absolute time. ... Negative values indicate relative time." and that "The actual timer accuracy depends on the capability of your hardware."
请注意,SetWaitableTimer()
使用“ 100 纳秒间隔......正值表示绝对时间。......负值表示相对时间。”和“实际计时器精度取决于硬件的能力。”
If you have a C++11 compiler then you can use thisportable version:
如果你有一个 C++11 编译器,那么你可以使用这个便携版本:
#include <chrono>
#include <thread>
...
std::this_thread::sleep_for(std::chrono::microseconds(usec));
Kudos to Howard Hinnant who designed the amazing <chrono>
library (and whose answer belowdeserves more love.)
感谢 Howard Hinnant 设计了这个惊人的<chrono>
图书馆(他的答案值得更多的爱。)
If you don't have C++11, but you have boost, then you can do thisinstead:
如果你没有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));
回答by Howard Hinnant
New answer for an old question:
旧问题的新答案:
Rationale for the new answer: Tools / OSs have been updated such that there is a better choice now than there was when the question was originally asked.
新答案的基本原理:工具/操作系统已更新,现在比最初提出问题时有更好的选择。
The C++11 <chrono>
and <thread>
std headers have been in the VS toolset for several years now. Using these headers this is best coded in C++11 as:
C++11<chrono>
和<thread>
std 头文件在 VS 工具集中已经存在好几年了。使用这些头文件最好在 C++11 中编码为:
std::this_thread::sleep_for(std::chrono::microseconds(123));
I'm using microseconds only as an example duration. You can use whatever duration happens to be convenient:
我仅使用微秒作为持续时间的示例。您可以使用任何方便的持续时间:
std::this_thread::sleep_for(std::chrono::minutes(2));
With C++14 and some using directives, this can be written a little bit more compactly:
使用 C++14 和一些 using 指令,这可以写得更紧凑一点:
using namespace std::literals;
std::this_thread::sleep_for(2min);
or:
或者:
std::this_thread::sleep_for(123us);
This definitely works on VS-2013 (modulo the chrono-literals). I'm unsure about earlier versions of VS.
这绝对适用于 VS-2013(以计时文字为模)。我不确定 VS 的早期版本。
回答by Arno
The millisecond regime of the Sleep()
function is well described and well understood. It does not do anything unpredictable. Sometimes the function is blamed to perform unpredictable, i.e. returning before the delay has expired. I need to say that this is wrong. Careful investigation will confirm that its behaviour is absolutely predictable. The only problem is
that there is plenty to read about it and most of it is kiddish. It is also often said that
windows it not a real-time OS. But such comments don't contribute anything, moreover such
comments are used to hide the lack of knowledge. It makes me sort of angry, that not even
microsoft notices this and provides better documentation.
该Sleep()
函数的毫秒范围得到了很好的描述和理解。它不会做任何不可预测的事情。有时该函数被指责执行不可预测,即在延迟到期之前返回。我需要说这是错误的。仔细调查将确认其行为是绝对可预测的。唯一的问题是有很多关于它的读物,而且大部分都是幼稚的。人们也常说 windows 不是实时操作系统。但是这样的评论并没有什么贡献,而且这样的评论是用来掩盖知识的缺乏的。这让我有点生气,甚至连微软都没有注意到这一点并提供了更好的文档。
However, without exaggerating this little answer: The sleep() function is precise, when used in a proper way and when knowing its characteristics. Particular attention has to be given to sleep(0). This is a very powerfull tool, particulary when used together with process priority class, thread priority, multimedia timer settings, and processor affinity mask.
但是,不要夸大这个小答案:sleep() 函数是精确的,只要以正确的方式使用并了解其特性。必须特别注意 sleep(0)。这是一个非常强大的工具,特别是与进程优先级、线程优先级、多媒体计时器设置和处理器关联掩码一起使用时。
So generally a true sleep can be performed easely and safe down to the systems interrupt period. When it comes to sleeps shorter than the interrupt period spinning is required.
A higher resolution time source has to be used in oder to spin for shorter periods in time.
The most common source for this is the performance counter. QueryPerformanceCounter(*arg)
delivers an incrementing *arg. QueryPerformanceFrequency(*arg)
delivers the frequency at which the performance counter increments. This is typically in the MHz regime and varies, depending on the underlying hardware. A frequency in the MHz range provides microsecond resolution. This way something of high resolution can be used to wait for a desired time span to expire. However, the accuracy of this has to be looked at carefully: The OS returns the performance counter frequency as a constant. This is wrong! Since the frequency is generated be a physical device, there is always an offset and it also not a
constant. It has thermal drift. More modern systems do have less drift. But if the thermal drift is just 1ppm, the error will be 1us/s. The offset can easely be several 100. An offset of 100 in 1MHz corresponds to 100us/s.
因此,通常可以在系统中断期间轻松且安全地执行真正的睡眠。当睡眠时间比需要的中断周期更短时。必须使用更高分辨率的时间源才能在更短的时间内旋转。最常见的来源是性能计数器。QueryPerformanceCounter(*arg)
提供一个递增的 *arg。QueryPerformanceFrequency(*arg)
提供性能计数器递增的频率。这通常在 MHz 范围内,并且因底层硬件而异。MHz 范围内的频率提供微秒级分辨率。通过这种方式,可以使用高分辨率的东西来等待所需的时间跨度到期。但是,必须仔细查看其准确性:操作系统将性能计数器频率作为常数返回。这是错误的!由于频率是由物理设备生成的,因此始终存在偏移并且也不是常数。它有热漂移。更现代的系统确实具有更少的漂移。但如果热漂移仅为 1ppm,则误差为 1us/s。偏移量很容易达到几百个。1MHz 的偏移量为 100 对应于 100us/s。
If a thread shall wait for any time at high resolution, it shall establish a service thread. Both thread shall share a named event. The service thread shall sleep until 1 interrupt period ahead of the desired sleep delay and then spin on the performance counter for the remaining microsecond. When the service thread reaches the final time, it set the named event and ends. The calling thread will wake up, because it was waiting for the named event by means of a wait function.
如果一个线程以高分辨率等待任何时间,它应该建立一个服务线程。两个线程应共享一个命名事件。服务线程应在所需的睡眠延迟之前休眠 1 个中断周期,然后在剩余的微秒内在性能计数器上旋转。当服务线程到达最后时间时,它设置命名事件并结束。调用线程将被唤醒,因为它正在通过等待函数等待命名事件。
Summary:
概括:
- Sleep is well understood but poorly documented.
- A service thread can mimic sleeps at high resolution.
- Such a service thread coulb be esablished as a system wide service.
- Accuracy of the performance counter is to be looked at carefully. A calibration is required.
- 睡眠很好理解,但记录很少。
- 服务线程可以在高分辨率下模拟睡眠。
- 这样的服务线程可以作为系统范围的服务来实现。
- 性能计数器的准确性需要仔细查看。需要校准。
More detailed information can be found at the Windows Timestamp Project
更多详细信息可以在Windows Timestamp Project 中找到
回答by Arno
It depends what granularity you need. If you are talking milliseconds, then the Win32 Sleep function will do the job - see http://msdn.microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx. If you are talking microseconds, then there is no easy way to do it, and you would be lucky to get that sort of timer resolution on Windows (which is not an RTOS), or on Linux, come to that.
这取决于您需要什么粒度。如果您说的是毫秒,那么 Win32 睡眠功能将完成这项工作 - 请参阅http://msdn.microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx。如果您说的是微秒,那么没有简单的方法可以做到,并且您很幸运能够在 Windows(不是 RTOS)或 Linux 上获得那种计时器分辨率,来实现这一点。
回答by orlp
I found this blog post about it. It uses QueryPerformanceCounter
. The function posted:
我找到了这篇关于它的博客文章。它使用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);
}
I hope this helps a bit.
我希望这个能有一点帮助。
回答by greywolf82
I'm quite late to the party but I want just to add something to this question. If you want to achieve portability using microseconds resolution than use select()
system call using empty file descriptor set. It will work both on linux and on windows, i.e. it can be called using an uniform interface (the behavior can be still different especially on Windows where you can ask for 1 microsecond but you get 1ms sleep). If you want to use a third-party library use Boost, but a recent version. The time related std api are just a mess and I provide a summary here:
我参加聚会已经很晚了,但我只想为这个问题添加一些内容。如果您想使用微秒分辨率实现可移植性,而不是使用select()
使用空文件描述符集的系统调用。它可以在 linux 和 windows 上工作,即可以使用统一接口调用它(行为仍然可能不同,尤其是在 Windows 上,您可以要求 1 微秒,但您可以获得 1 毫秒的睡眠)。如果要使用第三方库,请使用 Boost,但要使用最新版本。与时间相关的 std api 只是一团糟,我在这里提供了一个摘要:
- Windows: sleep_for, sleep_until, condition_variable, future and so on wait_for/wait_until methods are totally unreliable because they are based on system_clock, so if the time changes your application could hang. They fixed this problem internally but since it's an ABI break, they didn't release it yet, not available even on latest VS 2019.
- Linux: sleep_for, sleep_until are ok, but condition_variable/future wait_for/wait_until are unreliable because they are based too on system clock. It's fixed with Gcc 10 and GlibC 2.6 bug link.
- Boost: Same as above but they fixed time problems with version 1.67.
- Windows:sleep_for、sleep_until、condition_variable、future 等 wait_for/wait_until 方法完全不可靠,因为它们基于 system_clock,所以如果时间改变,您的应用程序可能会挂起。他们在内部修复了这个问题,但由于它是 ABI 中断,他们还没有发布它,即使在最新的 VS 2019 上也不可用。
- Linux:sleep_for、sleep_until 都可以,但 condition_variable/future wait_for/wait_until 不可靠,因为它们也基于系统时钟。它已通过 Gcc 10 和 GlibC 2.6错误链接修复。
- Boost:同上,但他们修复了 1.67 版的时间问题。
So if you want portable code make your own solution or just use Boost 1.67+, don't trust standard implementation c++11 chrono because the implementation performed is really bad.
因此,如果您希望可移植代码制作自己的解决方案或仅使用 Boost 1.67+,请不要相信标准实现 c++11 chrono,因为执行的实现非常糟糕。