2014年6月30日月曜日

時間で遅延してフラッシュするバッファー wonderland::data_structure::time_deferred_buffer_t を追加

Web Srorage へのアクセスが思いの外遅かった事もあって、結果的にフラッシュを時間で遅延するバッファーを書きました。
Wonderlandシリーズの例によって clang++-3.3 , g++-4.8.2 , em++-1.20.0 でビルド可能で、 native , Web , nodejs で動作するC++ヘッダーオンリーライブラリーです。



左から順に、 native(clang++), nodejs-0.10.25, Web(Ch-35) での example/deferred_buffer の動作の様子です。pushは100msごと、flushは500ms以上の経過を条件にしています。

time_deferred_buffer_t< T_element, T_clock > は T_element 型(default: std::string)の要素のバッファーで、 T_clock 型(default: std::chrono::steady_clock)で時間を測り、 push されてバッファーしている要素群に対して push から一定時間経過した要素群をまとめて flush します。

flush には任意の std::function<auto ( const flush_parameter_t&, const flush_parameter_t& ) -> void > 型の関数オブジェクトをセットでき、  flush_parameter_t 型は time_deferred_buffer_t 型が public メンバーとして公開する、内部で保持するデータ型( std::map< T_clock::time_point, T_element > 型)の ::const_iterator 型です。

↑こんな具合に flush を定義して使います。

push から flush へ送られるまでの最低限の遅延時間は delay メンバー関数に std::chrono::duration を渡して設定します。

    b -> delay( std::chrono::milliseconds( 500 ) );

↑こんな具合に delay を設定します。

どうやって遅延時間を評価して出力するかというと、

    b -> push_with_update( false );
    b -> auto_update( true );

この2つのメンバー関数の値が重要で、デフォルトでは push_with_update は true 、 auto_update は false になっています。本当はデフォルトを逆転させたかったのですが Emscripten というか Web API の現状では諦める事にしました。

push_with_update が true の場合には、 push されたタイミングで内部で自動的に update を呼び出します。

auto_update が true の場合には、内部で自動的に生成したワーカースレッドが delay で設定した遅延時間のスリープを挟みながら自動的に update を呼び出します。(但し、この機能は Emscripten でのビルドでは未サポートです(´・ω:;.:... )

update はバッファーが保持する T_element 型の要素群に対して push された時間をキーに std::map に整理してある内部データに対して [ cbegin .. std::map::upper_bound ) を基準として flush で設定されたフラッシュ関数オブジェクトに要素を渡し、処理後に要素を内部データから erase します。

また、 update は public メンバー関数なのでユーザーがよしなに直接呼び出しても動作します。 update は内部で前回 update 処理を行った時刻を保持と現在時刻を比較して、 delay 未満であれば処理をスキップします。

time_deferred_t はデストラクターが呼び出された際、全ての保持するバッファーの強制フラッシュ(public メンバー関数の force_flush )を呼び出します。

より具体的な使い方はリポジトリーの example/deferred_buffer.cxx をどうぞ。

0 件のコメント:

コメントを投稿