別の質問で、Windows/MingW が廃止された usleep() に代わる nanosleep() および setitimer() を提供していないことがわかりました。しかし、私の目標は、usleep() スタイルの警告を含め、cppcheck が私に与えるすべての警告を修正することです。
それで、 cygwinを使用したり、新しい依存関係/ライブラリのロードをインストールしたりせずに、Windowsでusleep()を回避する回避策はありますか? ありがとう。
古い質問に対する新しい回答:
新しい回答の根拠: ツール/OS が更新され、質問が最初に尋ねられたときよりも優れた選択肢が得られるようになりました。
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 ディレクティブを使用すると、これをもう少しコンパクトに書くことができます。
using namespace std::literals;
std::this_thread::sleep_for(2min);
また:
std::this_thread::sleep_for(123us);
これは間違いなく VS-2013 (クロノリテラルのモジュロ) で動作します。以前のバージョンの VS については不明です。
関数のミリ秒領域は、Sleep()
よく説明され、よく理解されています。予測不可能なことは何もしません。関数が予測不可能な動作をする、つまり遅延が終了する前に戻ると非難されることがあります。これは間違っていると言わざるを得ません。慎重な調査により、その動作が完全に予測可能であることが確認されます。唯一の問題は、それについて読むことがたくさんあり、そのほとんどが子供っぽいことです. Windows はリアルタイム OS ではないとよく言われます。しかし、そのようなコメントは何の貢献にもなりません。さらに、そのようなコメントは、知識の欠如を隠すために使用されます。マイクロソフトでさえこれに気付かず、より良いドキュメントを提供していないことに、私は腹を立てています。
ただし、この小さな答えを誇張することなく: sleep() 関数は、適切な方法で使用され、その特性を知っていれば正確です。sleep(0) には特に注意する必要があります。これは非常に強力なツールであり、特にプロセス優先度クラス、スレッド優先度、マルチメディア タイマー設定、およびプロセッサ アフィニティ マスクと一緒に使用すると効果的です。
そのため、通常、真のスリープは、システムの中断期間まで簡単かつ安全に実行できます。割り込み期間よりも短いスリープになると、回転が必要になります。より短い時間でスピンするには、より高い解像度の時間ソースを使用する必要があります。これの最も一般的な原因は、パフォーマンス カウンターです。QueryPerformanceCounter(*arg)
増加する *arg を提供します。QueryPerformanceFrequency(*arg)
パフォーマンス カウンターが増加する頻度を提供します。これは通常 MHz 単位であり、基盤となるハードウェアによって異なります。MHz 範囲の周波数は、マイクロ秒の分解能を提供します。このようにして、高解像度のものを使用して、目的の期間が満了するのを待つことができます。ただし、この精度は慎重に調べる必要があります。OS はパフォーマンス カウンターの頻度を定数として返します。これは間違っています!周波数は物理デバイスで生成されるため、常にオフセットがあり、定数ではありません。熱ドリフトがあります。最新のシステムでは、ドリフトが少なくなります。しかし、熱ドリフトがわずか 1ppm の場合、誤差は 1us/s になります。オフセットは簡単に数百になります。1MHz で 100 のオフセットは 100us/s に相当します。
スレッドが高解像度で待機する場合は、サービス スレッドを確立します。両方のスレッドが名前付きイベントを共有します。サービス スレッドは、目的のスリープ遅延の 1 割り込み時間前までスリープし、残りのマイクロ秒でパフォーマンス カウンターをスピンします。サービス スレッドが最終時間に達すると、名前付きイベントを設定して終了します。呼び出し元のスレッドは、待機関数によって指定されたイベントを待っていたため、ウェイク アップします。
概要:
詳細については、Windows タイムスタンプ プロジェクトを参照してください。
必要な粒度によって異なります。ミリ秒単位で話している場合は、Win32 Sleep 関数が機能します - 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);
}
これが少し役立つことを願っています。
usleep()
マイクロ秒で動作します。マイクロ秒の精度を取得するためのウィンドウでは、QueryPerformanceCounter() winapi 関数を使用する必要があります。ここでは、それを使用してその歳差を取得する方法を見つけることができます。