boost boost::cpu_timer 読んでみる
あいさつ
どうも、はかせです。
今回はboostを入れたときに最初に触った
boost::cpu_timerのコードを読んでみたいと思います。
読んでみる
まずは前回同様定義へジャンプしてみます。
class BOOST_TIMER_DECL cpu_timer { public: // constructor cpu_timer() BOOST_NOEXCEPT { start(); } // observers bool is_stopped() const BOOST_NOEXCEPT { return m_is_stopped; } cpu_times elapsed() const BOOST_NOEXCEPT; // does not stop() std::string format(short places, const std::string& format) const { return ::boost::timer::format(elapsed(), places, format); } std::string format(short places = default_places) const { return ::boost::timer::format(elapsed(), places); } // actions void start() BOOST_NOEXCEPT; void stop() BOOST_NOEXCEPT; void resume() BOOST_NOEXCEPT; private: cpu_times m_times; bool m_is_stopped; };
どうやらコンストラクタでstartメソッドを呼んでいるようです。
ではstartの実装に飛んでみます。
void cpu_timer::start() BOOST_NOEXCEPT { m_is_stopped = false; get_cpu_times(m_times); }
今のところホントにboostなのかってぐらい単純ですね。
timerのストップフラグを折って
get_cpu_timesというメソッドを呼んでいますね。
(なんか嫌な予感がするな)
じゃ次へ飛びましょう。
void get_cpu_times(boost::timer::cpu_times& current) { boost::chrono::duration<boost::int64_t, boost::nano> x (boost::chrono::high_resolution_clock::now().time_since_epoch()); current.wall = x.count(); # if defined(BOOST_WINDOWS_API) FILETIME creation, exit; if (::GetProcessTimes(::GetCurrentProcess(), &creation, &exit, (LPFILETIME)¤t.system, (LPFILETIME)¤t.user)) { current.user *= 100; // Windows uses 100 nanosecond ticks current.system *= 100; } else { current.system = current.user = boost::timer::nanosecond_type(-1); } # else tms tm; clock_t c = ::times(&tm); if (c == static_cast<clock_t>(-1)) // error { current.system = current.user = boost::timer::nanosecond_type(-1); } else { current.system = boost::timer::nanosecond_type(tm.tms_stime + tm.tms_cstime); current.user = boost::timer::nanosecond_type(tm.tms_utime + tm.tms_cutime); boost::int_least64_t factor; if ((factor = tick_factor()) != -1) { current.user *= factor; current.system *= factor; } else { current.user = current.system = boost::timer::nanosecond_type(-1); } } # endif }
なにやらメソッドを呼んで値を取得し、
マクロの分岐を使って環境ごとに取得した値に補正をかけて返しているようです。
ブログの文字数と私の理解力が限界を迎えつつあるので
一気に根っこまで行きます。
extern "C" { BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC QueryPerformanceCounter(::_LARGE_INTEGER* lpPerformanceCount); BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC QueryPerformanceFrequency(::_LARGE_INTEGER* lpFrequency); } // extern "C" BOOST_FORCEINLINE BOOL_ QueryPerformanceCounter(LARGE_INTEGER_* lpPerformanceCount) { return ::QueryPerformanceCounter(reinterpret_cast< ::_LARGE_INTEGER* >(lpPerformanceCount)); } BOOST_FORCEINLINE BOOL_ QueryPerformanceFrequency(LARGE_INTEGER_* lpFrequency) { return ::QueryPerformanceFrequency(reinterpret_cast< ::_LARGE_INTEGER* >(lpFrequency)); }
C言語登場≡\(・ω・)/ シュタッ
externということはどっかにあるC言語のメソッドを呼んでいるんですかね。
WinAPIに同じような名前のやつがあったので
多分それと似た動きをすると思います。
要はCPU時間をナノかミリかはわかりませんが
取得してきてくれるものでしょう。きっと。
つまりboost::cpu_timerは
①CPU時間を取得
②環境や設定に応じた値に修正
③formatメソッドを使いstringで値を返す
大雑把ですがこんな感じの処理をしているようです。
あとがき
今回はboost::cpu_timerのコードを読んでみました。
前回のlexical_castに比べて読みやすい印象を受けました。
まぁそれでも追いきれなくなったのでまだまだなんですけどね。
あと地味にこの記事で100記事目だったようです。
それでは今回はこの辺でノシ