/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /////////////////////////////////////////////////////////////////////////EA-V1 // $File: //depot/GeneralsMD/Staging/code/Libraries/Source/profile/profile.h $ // $Author: mhoffe $ // $Revision: #4 $ // $DateTime: 2003/08/14 13:43:29 $ // // ©2003 Electronic Arts // // Profiling module ////////////////////////////////////////////////////////////////////////////// #ifdef _MSC_VER # pragma once #endif #ifndef PROFILE_H // Include guard #define PROFILE_H #if defined(_DEBUG) && defined(_INTERNAL) #error "Only either _DEBUG or _INTERNAL should ever be defined" #endif // Define which libraries to use. #if defined(_INTERNAL) # pragma comment (lib,"profileinternal.lib") #elif defined(_DEBUG) # pragma comment (lib,"profiledebug.lib") #elif defined(_PROFILE) # pragma comment (lib,"profileprofile.lib") #else # pragma comment (lib,"profile.lib") #endif // include all our public header files (use double quotes here) #include "profile_doc.h" #include "profile_highlevel.h" #include "profile_funclevel.h" #include "profile_result.h" /** \brief Functions common to both profilers. */ class Profile { friend class ProfileCmdInterface; // nobody can construct this class Profile(); public: /** \brief Starts range recording. \param range name of range to record, ==NULL for "frame" */ static void StartRange(const char *range=0); /** \brief Appends profile data to the last recorded frame of the given range. \param range name of range to record, ==NULL for "frame" */ static void AppendRange(const char *range=0); /** \brief Stops range recording. \note After this call the recorded range data will be available as a new range frame. \param range name of range to record, ==NULL for "frame" */ static void StopRange(const char *range=0); /** \brief Determines if any range recording is enabled or not. \return true if range profiling is enabled, false if not */ static bool IsEnabled(void); /** \brief Determines the number of known (recorded) range frames. Note that if function level profiling is enabled then the number of recorded high level frames is the same as the number of recorded function level frames. \return number of recorded range frames */ static unsigned GetFrameCount(void); /** \brief Determines the range name of a recorded range frame. \note A unique number will be added to the frame name, separated by a ':', e.g. 'frame:3' \param frame number of recorded frame \return range name */ static const char *GetFrameName(unsigned frame); /** \brief Resets all 'total' counter values to 0. This function does not change any recorded frames. */ static void ClearTotals(void); /** \brief Determines number of CPU clock cycles per second. \note This value is cached internally so this function is quite fast. \return number of CPU clock cycles per second */ static _int64 GetClockCyclesPerSecond(void); /** \brief Add the given result function interface. \param func factory function \param name factory name \param arg description of optional parameters the factory function recognizes */ static void AddResultFunction(ProfileResultInterface* (*func)(int, const char * const *), const char *name, const char *arg); private: /** \internal \brief Simple recursive pattern matcher. \param str string to match \param pattern pattern, only wildcard valid is '*' \return true if string matches pattern, false if not */ static bool SimpleMatch(const char *str, const char *pattern); /// known frame names struct FrameName { /// frame name char *name; /// number of recorded frames for this name unsigned frames; /// are we currently recording? bool isRecording; /// should current frame be appended to last frame with same name bool doAppend; /// internal index for function level profiler int funcIndex; /// internal index for high level profiler int highIndex; /// global frame number of last recorded frame for this range, -1 if none int lastGlobalIndex; }; /// \internal pattern list entry struct PatternListEntry { /// next entry PatternListEntry *next; /// active (true) or inactive (false)? bool isActive; /// pattern itself (dynamic allocated memory) char *pattern; }; /** \internal First pattern list list entry. A singly linked list is okay for this because checking patterns is a costly operation anyway and is therefore cached. */ static PatternListEntry *firstPatternEntry; /// \internal last pattern list entry for fast additions to list at end static PatternListEntry *lastPatternEntry; /// number of recorded frames static unsigned m_rec; /// names of recorded frames static char **m_recNames; /// number of known frame names static unsigned m_names; /// list of known frame names static FrameName *m_frameNames; /// CPU clock cycles/second static _int64 m_clockCycles; }; #endif // PROFILE_H