実際には、その解像度の正確なタイマーを実装するのは単純なタスクではありません。非常に正確なタイマーを得るためには、おそらく独自の実行ループを実装する必要があります。動的タイマーの挿入/削除を伴う単一のタイマーしか必要としない場合は、実装が簡単です。
あなたが言ったように、while(...)ループを実行し、そこにはしばらくの間スリープ状態にする必要があります。これは最も難しい部分です。実際に経過した時間が実際の経過時間よりも大きくなる場合もありますが、実際の経過時間が実際の経過時間よりも長くなる場合もあります。
while(running) {
gettimeofday(&t_start, NULL);
{
double sleep_time = cur_timer->_M->nextFireTime() - elapsedTime;
if(sleep_time > 0) {
Thread::sleep(sleep_time); //sleep time is in seconds
}
}
gettimeofday(&t_end, NULL);
elapsedTime += Utils::timeval_diff(t_end, t_start);
if(running) {
gettimeofday(&t_start, NULL);
{
//perform all timer callbacks here
}
gettimeofday(&t_end, NULL);
}
elapsedTime += Utils::timeval_diff(t_end, t_start);
}
これは自分のrunloop実装の非常に単純化されたバージョンです。ここでの主なアイデアは、実際の経過時間を把握し、オーバーフローが発生したときにいつでも補う必要があるということです。ここで
は1msの時間ステップの出力例です:
period: 0.001000 (0.001000) elapsed: 0.001160 (0.001160)
period: 0.001000 (0.002000) elapsed: 0.000988 (0.002148)
period: 0.001000 (0.003000) elapsed: 0.000982 (0.003130)
period: 0.001000 (0.004000) elapsed: 0.001003 (0.004133)
period: 0.001000 (0.005000) elapsed: 0.001004 (0.005137)
.....
period: 0.001000 (4.280872) elapsed: 0.001022 (4.299592)
period: 0.001000 (4.281872) elapsed: 0.002627 (4.302219)
period: 0.001000 (4.282872) elapsed: 0.000018 (4.302237)
period: 0.001000 (4.283872) elapsed: 0.000266 (4.302503)
period: 0.001000 (4.284872) elapsed: 0.001091 (4.303594)
period: 0.001000 (4.285872) elapsed: 0.001026 (4.304620)
も、より正確な結果は、優先度の高い別のスレッドでタイマーを実行する取得するには。
出典
2011-12-26 10:46:01
Max
ありがとう、あなたの答えはたくさんありましたが、あなたが言った多くのこと、そしてコードそのものを理解できませんでした。まず、私はwhile(1)ループを実行し、そこに必要なものをやりますか?なぜ私は睡眠を取らなければならないのですか?プロセッサーが他のものをやってくれるようにするにはどうすればいいですか?そうすれば、500usのようにsleep()メソッドをやってみませんか?とにかくあなたのコードが達成しようとしていることを理解できませんでした。 – Curnelious
あなたはwhile(1)を使うことができますが、breakを使って実行ループを停止する必要があります。あなたはあまりにも時間を制御するタイマーをスリープ状態にしている。 – Max
私は今すぐ見ることができます。私はこれもNSDateを使うように言われました。それも大丈夫ですか? – Curnelious