web-dev-qa-db-ja.com

c ++、usleep()は廃止され、Windows / MingWの回避策ですか?

Windows/MingWには、廃止されたusleep()に代わるnanosleep()およびsetitimer()の代替物がないことを別の質問で発見しました。しかし、私の目標は、usleep()スタイルの警告を含め、cppcheckから得られるすべての警告を修正することです。

だから、Windowsでusleep()を何らかの方法で回避する回避策はありますか?without cygwinを使用するか、新しい依存関係/ライブラリの負荷をインストールしますか?ありがとう。

22
blubberbernd

私はこのコードを(元々 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));
_

素晴らしい_<chrono>_ライブラリを設計したハワードヒナントへの称賛(および 以下の回答 はより多くの愛に値します。)

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));
_
46
Adi Shavit

古い質問に対する新しい回答:

新しい回答の理由:ツール/ 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の以前のバージョンについてはわかりません。

12
Howard Hinnant

Sleep()関数のミリ秒レジームは十分に説明され、よく理解されています。予測できないことは何もしません。関数は予測不可能な実行、つまり遅延が終了する前に戻ると非難されることがあります。これは間違っていると言う必要があります。慎重な調査により、その動作が完全に予測可能であることが確認されます。唯一の問題は、それについて読むことがたくさんあり、そのほとんどが子供っぽいということです。また、WindowsはリアルタイムOSではないとよく言われます。しかし、そのようなコメントは何の貢献もせず、さらにそのようなコメントは知識不足を隠すために使用されます。 Microsoftでさえこれに気づかず、より良いドキュメントを提供しているので、私はちょっと怒っています。

ただし、この小さな答えを誇張することなく、適切な方法で使用し、その特性を知っているとき、sleep()関数は正確です。 sleep(0)には特に注意する必要があります。これは非常に強力なツールであり、特にプロセス優先度クラス、スレッド優先度、マルチメディアタイマー設定、およびプロセッサアフィニティマスクと併用すると効果的です。

そのため、通常、システムの割り込み期間まで、真のスリープを簡単かつ安全に実行できます。スリープになると、割り込み周期よりも短く回転する必要があります。短時間でスピンするには、より高い解像度の時間ソースを使用する必要があります。これの最も一般的なソースはパフォーマンスカウンターです。 QueryPerformanceCounter(*arg)は、インクリメントする* argを提供します。 QueryPerformanceFrequency(*arg)は、パフォーマンスカウンターが増加する頻度を提供します。これは通常、MHz領域であり、基盤となるハードウェアによって異なります。 MHz範囲の周波数は、マイクロ秒の分解能を提供します。このように、高解像度のものを使用して、希望する期間が終了するのを待つことができます。ただし、この精度は慎重に確認する必要があります。OSはパフォーマンスカウンターの周波数を定数として返します。これは間違っています!周波数は物理デバイスで生成されるため、常にオフセットがあり、定数でもありません。熱ドリフトがあります。最新のシステムではドリフトが少なくなります。ただし、熱ドリフトがわずか1ppmの場合、誤差は1us/sになります。オフセットは簡単に数100にすることができます。1MHzで100のオフセットは100us/sに相当します。

スレッドが高解像度でいつでも待機する場合、スレッドはサービススレッドを確立します。両方のスレッドは名前付きイベントを共有します。サービススレッドは、目的のスリープ遅延の1割り込み期間前にスリープし、残りのマイクロ秒の間、パフォーマンスカウンターをスピンします。サービススレッドが最終時間に達すると、名前付きイベントを設定して終了します。呼び出しスレッドは、待機関数によって名前付きイベントを待機していたため、起動します。

概要:

  • 睡眠はよく理解されていますが、文書化されていません。
  • サービススレッドは、高解像度でスリープを模倣できます。
  • このようなサービススレッドは、システム全体のサービスとして確立されます。
  • パフォーマンスカウンターの精度を注意深く調べる必要があります。キャリブレーションが必要です。

より詳細な情報は Windows Timestamp Project にあります。

8
Arno

このブログ投稿について が見つかりました。 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);
}

これが少し役立つことを願っています。

5
orlp

必要な粒度に依存します。ミリ秒を話す場合、Win32スリープ機能がジョブを実行します- http://msdn.Microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx を参照してください=。マイクロ秒を話す場合、それを行う簡単な方法はありません。Windows(RTOSではありません)またはLinuxでその種のタイマー解決を実現できれば幸運です。

5