チェックポイントを書いています。ループを実行するたびにチェックしています。これにより、多くのCPU時間が浪費されると思います。システム時刻を 10 秒ごとに確認する方法を教えてください。
time_t start = clock();
while(forever)
{
if(difftime(clock(),start)/CLOCKS_PER_SEC >=timeLimit)
{
break;
}
}
非常に短い答えは、初心者のプログラマーにとって、これは非常に難しいということです。
いくつかの可能性があります:
10 秒間スリープします。つまり、あなたのプログラムは基本的に無意味です。
alarm()
ハンドラーを使用して信号を送ります。シグナル ハンドラー内で特別なことを行ってはならないため、これを正しく行うのは困難です。
を使用してtimerfd
、タイミング ロジックを I/O ループに統合します。
タイマー専用のスレッドをセットアップします (その後、スリープすることができます)。すべての共有データ アクセスを同期することを考える必要があるため、これは非常に困難です。
ここで重要なのは、問題には単純な解決策がないということです。タイミング ロジックを既存のプログラム フローに深く統合する必要があります。このフローは、ある種の「メイン ループ」 (たとえば、epoll_wait
またはのような I/O 多重化ループselect
) であり、場合によってはマルチスレッドである必要があり、そのループはタイマーが起動したという事実を取得する必要があります。
それほど簡単ではありません。
これは接線であり、おそらく有益です。基本的に 2 種類のコンピューター プログラムがあります (他のすべての種類は別として)。
1 つは、1 つの特定のタスクを可能な限り効率的に実行し、その後完了するプログラムです。これは、たとえば、「SSL キー ペアを生成する」、または「X に一致するファイル内のすべての行を検索する」などです。これらは、プログラムの流れに関する限り、書きやすく理解しやすい種類のプログラムです。
もう 1 つの種類は、ユーザーと対話するプログラムです。これらのプログラムは無期限に稼働し続け、ユーザーの入力に応答します。(基本的にはあらゆる種類の UI やゲームですが、Web サーバーも同様です。) 制御フローの観点から見ると、これらのプログラムはほとんどの時間を何もせずに費やしています。ユーザーの入力を待っているだけです。では、これをどのようにプログラムするかを考えるとき、どのようにしてプログラムに何もさせないのでしょうか? これが「メイン ループ」の心臓部です。これは、興味深いことが起こるまでプロセスをスリープ状態に保つよう OS に指示し、次に興味深いイベントを処理してからスリープ状態に戻るループです。
何もしない方法を理解するまでは、第 2 種のプログラムを設計することはできません。
精度が必要な場合は、select() の呼び出しを null パラメーターで行うことができますが、遅延が発生します。これはミリ秒単位の精度です。
struct timeval timeout= {10, 0};
select(1,NULL,NULL,NULL, &timeout);
そうでない場合は、sleep() を使用してください。
sleep(10);
プログラムでイベント ループを使用し、タイマーをスケジュールしてコールバックを実行できます。たとえば、libevを使用してイベント ループを作成し、タイマーを追加できます。
ev_timer_init (timer, callback, 0., 5.);
ev_timer_again (loop, timer);
...
timer->again = 17.;
ev_timer_again (loop, timer);
...
timer->again = 10.;
ev_timer_again (loop, timer);
特定のツールキットでコーディングする場合は、他のイベント ループを使用できます。gtk、qt、glib には独自のイベント ループがあるため、それらを使用できます。
(シングル スレッド環境での) 最も簡単な方法は、しばらくスリープ状態にして、合計待機時間が経過したかどうかを繰り返し確認することです。
int sleepPeriodMs = 500;
time_t start = clock();
while(forever)
{
while(difftime(clock(),start)/CLOCKS_PER_SEC <timeLimit) // NOTE: Change of logic here!
{
sleep(sleepPeriod);
}
}
sleep()
あまり正確ではないことに注意してください。より高い精度のタイミング (つまり、10 ミリ秒以上の分解能) が必要な場合は、さらに深く掘り下げる必要があるかもしれません。また、C++11 には、<chrono>
より多くの機能を提供するヘッダーがあります。
using namespace std::chrono;
int sleepPeriodMs = 500;
time_t start = clock();
while(forever)
{
auto start = system_clock()::now()
// do some stuff that takes between [0..10[ seconds
std::this_thread::sleep_until(start+seconds(10));
}
システムに CPU 時間を与えるためにsleepの呼び出しを追加するだけです。
time_t start = clock();
while(forever)
{
if(difftime(clock(),start)/CLOCKS_PER_SEC >=timeLimit)
{
break;
}
sleep(1); // <<< put process to sleep for 1s
}