2012-06-26 8 views
22

C++ 11では、安定したクロック(すなわち、変化しないレートでのみ前進するクロック)が使用されている場合にのみ、*_untilタイムアウト関数が「期待どおり」に動作します。対応する* _for関数の代わりにC++ 11 * _untilタイムアウト関数を使用するのが適切なのはいつですか?

using namespace std::chrono; 
std::this_thread::sleep_until(system_clock::now() + seconds(10)); 

をこれは、例えば、システムクロックはスリープ期間中に調整されていない限り、現在のスレッドが10秒間スリープ状態に発生します:system_clockが安定したクロックではないので、それはこのようなコードはかなり意外に振る舞うことができることを意味し夏時間用です。スリープ中に1時間前にクロックを戻すと、現在のスレッドは1時間10秒間スリープ状態になります。

私が知ることから、C++ 11のすべての*_untilタイムアウト関数には対応する*_for関数があり、タイムポイントの代わりに時間がかかります。たとえば、次のように上記のコードを書き換えることができます:*_for機能は、彼らはただ、ない待機する時間を言うので、機能が実行されている間に調整しますクロックを心配する必要はありません

using namespace std::chrono; 
std::this_thread::sleep_for(seconds(10)); 

何待ち時間が終わったときの時間です。

この問題は、futureおよびtry_lock関数のタイムアウトベースの待機にも同じことが当てはまります。

あなたはは、アカウントにクロックの調整をしたいとき、私は非定常クロックで*_until機能を使用する意味を作り、それを思い描くことができる唯一の状況は、例えば、だろう、あなたは3で次水曜日まで眠りたいです:たとえ今と今の間に夏時間の変更があったとしても、30AMです。 *_until関数が*_for関数よりも意味を成す他の状況はありますか?そうでない場合は、一般に*_forタイムアウト関数を*_until関数よりも優先させるべきですか?

+0

_clock_の_steadiness_に依存しませんか? 'wait_for'と' wait_until'は本当に 'クロックジャンプ'の扱いが違うのですか? –

+0

@ K-ballo:そうですね、私は特にクロックの安定性について言及しており、system_clockは安定していません。 '_for'関数と' _until'関数は時計の調整とは異なった振る舞いをしますが、_intention_は何もわかりません。 – KnowItAllWannabe

+1

'system_clockの_steadiness_は実際には実装に依存します。 –

答えて

9

xxxx_untilは、期限が切れた場合のコールです。典型的なユースケースは、複数の待機を含むコードセクション、または待機前の各ステップで費やされる時間が予測できないコードセクションに厳しい制限がある場合です。

void foo() { 
    std::chrono::steady_clock::time_point const timeout= 
    std::chrono::steady_clock::now()+std::chrono::milliseconds(30); 

    do_something_which_takes_some_time(); 

    if(some_future.wait_until(timeout)==std::future_status::ready) 
    do_something_with(some_future.get()); 
} 

それはdo_something_which_takes_some_time()に要する時間を含む開始から30ミリ秒、内部準備ができている場合にのみsome_futureから値を処理します。

この例のように、xxxx_until関数のほとんどの使用例は、予測可能なタイムアウトを得るために安定したクロックを使用します。

タイムアウトがユーザに表示され、選択されたクロックの値に依存する私は(例えばstd::chrono::system_clockなど)、非定常的なクロックとXXX_until関数を使用して想像することができる唯一の場合です。目覚まし時計またはリマインダプログラムは一例であり、「深夜に」実行されるバックアッププログラムは別のものである。

4

sleep_until機能の1つの使用例は、特定の時間までで、特定の時間までスリープ状態にしたい場合です。

たとえば、毎日午後3時にのみアクティブにする必要があるスレッドがある場合は、夏時間と閏年の処理を含む、sleep_forで計算するか、sleep_untilを使用する必要があります。

+1

目覚まし時計は、夏時間を考慮に入れた優れた例です。あなたの勤務時間はDSTに調整されているので、あなたの目覚まし時計も調整してください。 –

2

sleep_untilの1つの良い用途は、(ゲームループのような)定常時のループです。サイクルの処理にどれくらいの時間がかかるかわからないが、通常はが一定の最小長でなければならない場合は、サイクル時間までスリープするようにtime_pointを増分することができます。たとえば:

// requires C++14 
#include <iostream> 
#include <thread> 
#include <chrono> 

using namespace std; 
using namespace std::chrono; 
using namespace std::literals; 

int main() 
{ 
    auto start_time = steady_clock::now(); 

    for (auto i = start_time; i <= start_time + 1s; i += 50ms) { 
    this_thread::sleep_until(i); 
    cout << "processing cycle..." << endl; 
    } 

    return 0; 
} 

しかし、あなたはおそらくサイクルはインクリメント時間よりも長くを取るときの遅れを追跡するようになってきました。

あなたが純粋にsleep_forなら、あなたのサイクル期間のループルコードを実行するのに慣れているという考えがあります。

関連する問題