/*---------------------------------------------------------------------------* Project: NintendoWare File: lyt_Stopwatch.h Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. The content herein is highly confidential and should be handled accordingly. $Revision: 31311 $ *---------------------------------------------------------------------------*/ #ifndef NW_LYT_STOPWATCH_H_ #define NW_LYT_STOPWATCH_H_ #include #include #include #include #ifdef NW_PLATFORM_CTR #include #endif namespace nw { namespace lyt { namespace internal { #define NW_LYT_PROFILE 1 #ifdef NW_LYT_PROFILE # define NW_LYT_JOIN(x, y) NW_LYT_JOIN_AGAIN(x, y) # define NW_LYT_JOIN_AGAIN(x, y) x ## y # define NW_LYT_STOPWATCH_MEASURE(no, label) \ nw::lyt::internal::Measure NW_LYT_JOIN(measure, __LINE__) ( \ nw::lyt::internal::Stopwatch::Instance(label), no) # define NW_LYT_STOPWATCH_START(no, label) \ if(nw::lyt::internal::Stopwatch::IsTarget(no)) \ nw::lyt::internal::Stopwatch::Instance().Start(label) # define NW_LYT_STOPWATCH_STOP(no) \ if(nw::lyt::internal::Stopwatch::IsTarget(no)) \ nw::lyt::internal::Stopwatch::Instance().Stop() #else # define NW_LYT_STOPWATCH_MEASURE(no, label) # define NW_LYT_STOPWATCH_START(no, label) # define NW_LYT_STOPWATCH_STOP(no) #endif #ifdef NW_PLATFORM_CTR using nn::fnd::TimeSpan; using nn::os::Tick; #endif //--------------------------------------------------------------------------- //! 経過時間を計測します。 //--------------------------------------------------------------------------- class Stopwatch : public nw::ut::LinkListNode { public: static const s64 S64_MAX = (s64)(((u64)-1) >> 1); //! インスタンスを保持するリストです。 typedef nw::ut::LinkList List; //! @brief コンストラクタです。 Stopwatch(int no = 0, const char* label = NULL); //! @brief 計測を開始します。 //! //! @param label 計測対象を示すラベルを指定できます。 //! void Start(const char* label = NULL) { #ifndef NW_PLATFORM_CTR NW_UNUSED_VARIABLE(label) #else if (label != NULL) { this->SetLabel(label); } NW_ASSERT(!this->IsRunning()); m_StartTick = Tick::GetSystemCurrent(); #endif } //! @brief 計測を停止します。 void Stop() { #ifdef NW_PLATFORM_CTR Tick stopTick = Tick::GetSystemCurrent(); NW_ASSERT(this->IsRunning()); Tick elapsed = stopTick - m_StartTick; m_StartTick = Tick(); if (s64(elapsed) < m_MinSample) { m_MinSample = s64(elapsed); } if (s64(elapsed) > m_MaxSample) { m_MaxSample = s64(elapsed); } m_TotalTick += elapsed; ++m_Count; #endif } void Reset(); static void ResetAll(); //! @brief 番号を設定します。 void SetNo(int no) { #ifndef NW_PLATFORM_CTR NW_UNUSED_VARIABLE(no); #else m_No = no; #endif } //! @brief ラベルを設定します。 void SetLabel(const char* label) { #ifndef NW_PLATFORM_CTR NW_UNUSED_VARIABLE(label); #else m_Label = label; #endif } #ifdef NW_PLATFORM_CTR //! @brief 計測中か調べます。 bool IsRunning() const { return m_StartTick != Tick(); } //! @brief 番号を取得します。 int GetNo() const { return m_No; } //! @brief ラベルを取得します。 const char* GetLabel() const { return m_Label; } //! @brief 経過時間の合計を取得します。 const TimeSpan GetElapsedTime() const { return m_TotalTick; } //! @brief 測定回数を取得します。 int GetCount() const { return m_Count; } //! @brief 最小値のサンプルを取得します。 TimeSpan GetMinSample() const { if (m_Count == 0) { return Tick(0).ToTimeSpan(); } else { return Tick(m_MinSample).ToTimeSpan(); } } //! @brief 最大値のサンプルを取得します。 TimeSpan GetMaxSample() const { if (m_Count == 0) { return Tick(0).ToTimeSpan(); } else { return Tick(m_MaxSample).ToTimeSpan(); } } #endif //! @brief インスタンスを取得します。 //! //! @tparam no 計測対象に固有の番号を指定します。 //! @param label 計測対象を示すラベルが指定できます。 //! template static Stopwatch& Instance(const char* label = NULL) { static Stopwatch obj(no); if (label != NULL) { obj.SetLabel(label); } return obj; } //! @brief インスタンスのリストを取得します。 static List& GetList() { static List list; return list; } //! @brief 計測を有効にします。 //! @details //! SetTargetNo() で全インスタンス番号を指定するのと等価です。 static void Enable(); //! @brief 計測を無効にします。 //! @details //! SetTargetNo() で min > max を指定するのと等価です。 static void Disable(); //! @brief インスタンス番号が計測対象かどうかを判定します。 static bool IsTarget(int no) { return s_TargetNoMin <= no && no <= s_TargetNoMax; } //! @brief 計測対象とするインスタンス番号の範囲を設定します。 static void SetTargetNo(int min, int max) { s_TargetNoMin = min; s_TargetNoMax = max; } //! @brief 計測対象とするインスタンス番号を設定します。 static void SetTargetNo(int no) { SetTargetNo(no, no); } //! @brief 計測結果をコンソールに出力します。 static void Dump(const Stopwatch& stopwatch); //! @brief すべての計測結果をコンソールに出力します。 static void Dump(); //! @brief 計測結果のヘッダを出力します。 static void DumpHeader(); protected: #ifdef NW_PLATFORM_CTR //! @details :private int m_Count; //! @details :private int m_No; //! @details :private const char* m_Label; //! @details :private Tick m_TotalTick; //! @details :private Tick m_StartTick; //! @details :private s64 m_MinSample; //! @details :private s64 m_MaxSample; #endif //! @details :private static int s_TargetNoMin; //! @details :private static int s_TargetNoMax; }; //--------------------------------------------------------------------------- //! 計測の開始と終了を自動化します。 //--------------------------------------------------------------------------- class Measure { public: Measure(Stopwatch& stopwatch, int no) : m_Stopwatch(stopwatch) { #ifdef NW_PLATFORM_CTR if(Stopwatch::IsTarget(no)) { m_Stopwatch.Start(); } #endif } ~Measure() { #ifdef NW_PLATFORM_CTR if(m_Stopwatch.IsRunning()) { m_Stopwatch.Stop(); } #endif } protected: //! @details :private Stopwatch& m_Stopwatch; }; } // namespace internal } // namespace lyt } // namespace nw #endif // NW_LYT_STOPWATCH_H_