2014年4月5日土曜日

release: libWRP-time // C++ time helper function header-only library


今回は時間を絡めた処理でよく必要になる機能をヘルパー関数としてまとめたC++のヘッダーオンリーライブラリー libWRP-time をリリースしました。libWRP-timeもEmscriptenとPC向けのClangとGCCに対応しています。

左はリポジトリーのexampleをEmscriptenで、右はClang++-3.2を使ってそれぞれビルドして実行した様子です。

version 1.0.0 公開現在の機能は、
  1. time
  2. adjust
  3. for_time_until
  4. adjust_loop_with_skipping
の4つです。

それぞれ、

[1. time]

`auto dt = time( some_function )`とすると、`dt`に`some_function`に要した処理時間がstd::chrono::nanosecond(関数のテンプレート引数で変更可能)で得られます。お約束のいわゆる簡易ストップウォッチ機能です。

内部で使用する時計はデフォルトではstd::chrono::high_resolution_clockですが、それもテンプレート引数で変更可能です。

[2. adjust]

`auto dt = adjust( some_function, milliseconds(100) )`とすると、`some_function`に要した処理時間が、もし目標とする`milliseconds(100)`に満たなかった場合には、必要なスリープ処理をstd::this_thread_sleep_forにより行います。`dt`には与えた`milliseconds(100)`との偏差時間が得られます。例えばちょうどピッタリmilliseconds(100)で処理できた場合にはdtには0、処理に40msしかかからず60msのウェイトが必要だった場合には60、処理に120msかかり-20msの遅延が生じて閉まっていた場合には-20が得られます。得られる時間の型はデフォルトではstd::chrono::nanosecondsですが、テンプレート引数により変更可能です。

これは、例えば可能な限りは毎秒30回のペースで処理したい some_function がある場合に、処理速度が早ければ自動的にウェイトを掛けつつ処理する目的で使えます。

[3. for_time_until]

`for_time_until( some_function, high_resolution_clock::now() + seconds(1) )`とすると、`some_function`を`high_resolution_clock::now() + seconds(1)`までの間に可能な限り繰り返します。

何のことは無い while(<condition>) some_function(); で一定の時刻(std::chrono::time_point)まで可能な限り some_function を繰り返し処理させているだけだったりします。

[4. adjust_loop_with_skipping]

`adjust_loop_with_skipping( some_function,  milliseconds(100), condition_to_continue_ref )`とすると、内部的にconst bool&で受け取る`condition_to_continue_ref`がtrueの間、`adjust( some_function, milliseconds(100) )`をループ処理します。その際に、内部的にループ処理中の`adjust( some_function, milliseconds(100) )`の結果得られている偏差時間を加算し、もしもこれが負の値となった場合、つまり目標とする100msよりも余計に処理時間を要してしまっている場合には、 some_function を処理せずにスキップしつつ目標処理時間の milliseconds(100) を偏差時間に加算します。

100ms間隔で実行したい some_function があるが、多少処理時間が多くなったり少なくなったり変動する可能性がある場合に、処理時間に余裕がある場合にはウェイトを掛けつつ目標の100ms間隔で処理を行い、処理時間が目標よりも多く必要だった場合には次のループでの処理を行わずにスキップし過負荷を回避する用途で使います。

adjust_loop_with_skippingには省略可能な4つめの引数としてスキップ処理時のフック関数を与えることもできます。exampleではスキップ処理時にその旨をstd::cerrに表示しつつ、10回スキップ処理が発生したらループを抜けるフックを例として記述しています。

より具体的な使い方はリポジトリー付属の example や、ライブラリーのシグニチャーや実装からどうぞ。

0 件のコメント:

コメントを投稿