diff --git a/Editor/Sector Summary.cpp b/Editor/Sector Summary.cpp
index 8897394a..d90f8b35 100644
--- a/Editor/Sector Summary.cpp
+++ b/Editor/Sector Summary.cpp
@@ -95,7 +95,7 @@ INT32 giCurrentViewLevel = ALL_LEVELS_MASK;
BOOLEAN gbSectorLevels[16][16];
BOOLEAN gfGlobalSummaryLoaded = FALSE;
-SUMMARYFILE *gpSectorSummary[16][16][8];
+SUMMARYFILE *gpSectorSummary[16][16][8] = {};
SUMMARYFILE *gpCurrentSectorSummary;
MOUSE_REGION MapRegion;
@@ -2419,6 +2419,8 @@ void LoadGlobalSummary()
if( gfMustForceUpdateAllMaps )
{
OutputDebugString( (LPCSTR)String( "A MAJOR MAP UPDATE EVENT HAS BEEN DETECTED FOR %d MAPS!!!!.\n", gusNumberOfMapsToBeForceUpdated ) );
+ //ADB update it!
+ ApologizeOverrideAndForceUpdateEverything();
}
@@ -2503,6 +2505,11 @@ void WriteSectorSummaryUpdate( STR8 puiFilename, UINT8 ubLevel, SUMMARYFILE *pSu
else
x = (puiFilename[ 1 ] - '0') * 10 + puiFilename[ 2 ] - '0' - 1;
+ if( gpSectorSummary[x][y][ubLevel] )
+ {
+ MemFree( gpSectorSummary[x][y][ubLevel] );
+ gpSectorSummary[x][y][ubLevel] = NULL;
+ }
gpSectorSummary[x][y][ubLevel] = pSummaryFileInfo;
// Snap: Restore the data directory once we are finished.
@@ -2568,6 +2575,9 @@ void LoadSummary( STR8 pSector, UINT8 ubLevel, FLOAT dMajorMapVersion )
if( !fp )
{
gusNumEntriesWithOutdatedOrNoSummaryInfo++;
+ //ADB don't forget that these might need to be updated!!!
+ gusNumberOfMapsToBeForceUpdated++;
+ gfMustForceUpdateAllMaps = TRUE;
return;
}
fread( &temp, 1, sizeof( SUMMARYFILE ), fp );
@@ -2731,16 +2741,23 @@ void SummaryUpdateCallback( GUI_BUTTON *btn, INT32 reason )
SetProgressBarTitle( 0, L"Generating map summary", BLOCKFONT2, FONT_RED, FONT_NEARBLACK );
SetProgressBarMsgAttributes( 0, SMALLCOMPFONT, FONT_BLACK, FONT_BLACK );
+#if 0
+ // 0verhaul: This should NOT be freed. An array index can be freed when it is recalculated,
+ // as this function is about to do. And then it SHOULD be freed first, which it wasn't doing.
+ // Either way, using this pointer is not a safe way to free the current sector's summary data.
if( gpCurrentSectorSummary )
{
MemFree( gpCurrentSectorSummary );
gpCurrentSectorSummary = NULL;
}
+#endif
sprintf( str, "%c%d", gsSelSectorY + 'A' - 1, gsSelSectorX );
EvaluateWorld( str, (UINT8)giCurrLevel );
- gpSectorSummary[ gsSelSectorX ][ gsSelSectorY ][ giCurrLevel ] = gpCurrentSectorSummary;
+ // ADB: The current sector summary should be set to the array value, not the other way around.
+ // Also the sector X and Y values are 1-based and the array is 0-based. So subtract 1 from X and Y
+ gpCurrentSectorSummary = gpSectorSummary[ gsSelSectorX - 1][ gsSelSectorY - 1][ giCurrLevel ];
gfRenderSummary = TRUE;
@@ -2765,7 +2782,7 @@ void ExtractTempFilename()
void ApologizeOverrideAndForceUpdateEverything()
{
INT32 x, y;
- CHAR16 str[ 50 ];
+ CHAR16 str[ 128 ];
CHAR8 name[50];
SUMMARYFILE *pSF;
//Create one huge assed button
@@ -2883,7 +2900,8 @@ void ApologizeOverrideAndForceUpdateEverything()
}
}
- EvaluateWorld( "p3_m.dat", 0 );
+ // ADB: The call to EvaluateWorld does not use the .dat extension
+ EvaluateWorld( "p3_m", 0 );
RemoveProgressBar( 2 );
gfUpdatingNow = FALSE;
@@ -2933,7 +2951,6 @@ void SetupItemDetailsMode( BOOLEAN fAllowRecursion )
if( gpCurrentSectorSummary->ubSummaryVersion == GLOBAL_SUMMARY_VERSION )
gusNumEntriesWithOutdatedOrNoSummaryInfo++;
SummaryUpdateCallback( ButtonList[ iSummaryButton[ SUMMARY_UPDATE ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
- gpCurrentSectorSummary = gpSectorSummary[ gsSelSectorX - 1 ][ gsSelSectorY - 1 ][ giCurrLevel ];
}
//Open the original map for the sector
sprintf( szFilename, "MAPS\\%S", gszFilename );
@@ -2942,21 +2959,28 @@ void SetupItemDetailsMode( BOOLEAN fAllowRecursion )
{ //The file couldn't be found!
return;
}
- //Now fileseek directly to the file position where the number of world items are stored
- if( !FileSeek( hfile, gpCurrentSectorSummary->uiNumItemsPosition, FILE_SEEK_FROM_START ) )
- { //Position couldn't be found!
- FileClose( hfile );
- return;
- }
- //Now load the number of world items from the map.
- FileRead( hfile, &uiNumItems, 4, &uiNumBytesRead );
- if( uiNumBytesRead != 4 )
- { //Invalid situation.
- FileClose( hfile );
- return;
+ // ADB: The uiNumItemsPosition may be 0 here due to the recursion further down.
+ // If so, skip the read
+ uiNumItems = 0;
+ if (gpCurrentSectorSummary->uiNumItemsPosition)
+ {
+ //Now fileseek directly to the file position where the number of world items are stored
+ if( !FileSeek( hfile, gpCurrentSectorSummary->uiNumItemsPosition, FILE_SEEK_FROM_START ) )
+ { //Position couldn't be found!
+ FileClose( hfile );
+ return;
+ }
+ //Now load the number of world items from the map.
+ FileRead( hfile, &uiNumItems, 4, &uiNumBytesRead );
+ if( uiNumBytesRead != 4 )
+ { //Invalid situation.
+ FileClose( hfile );
+ return;
+ }
}
+
//Now compare this number with the number the summary thinks we should have. If they are different,
- //the the summary doesn't match the map. What we will do is force regenerate the map so that they do
+ //then the summary doesn't match the map. What we will do is force regenerate the map so that they do
//match
if( uiNumItems != gpCurrentSectorSummary->usNumItems && fAllowRecursion )
{
@@ -3108,4 +3132,22 @@ UINT8 GetCurrentSummaryVersion()
return 0;
}
+void ClearSummaryInfo()
+{
+ for (int x = 0; x < 16; x++)
+ {
+ for (int y=0; y < 16; y++)
+ {
+ for (int z=0; z < 8; z++)
+ {
+ if (gpSectorSummary[x][y][z])
+ {
+ MemFree( gpSectorSummary[x][y][z]);
+ gpSectorSummary[x][y][z] = NULL;
+ }
+ }
+ }
+ }
+}
+
#endif
\ No newline at end of file
diff --git a/Editor/Summary Info.h b/Editor/Summary Info.h
index 2009c1ec..cc2885ab 100644
--- a/Editor/Summary Info.h
+++ b/Editor/Summary Info.h
@@ -104,6 +104,7 @@ extern void WriteSectorSummaryUpdate( STR8 puiFilename, UINT8 ubLevel, SUMMARYFI
extern BOOLEAN gfMustForceUpdateAllMaps;
extern BOOLEAN gfMajorUpdate;
void ApologizeOverrideAndForceUpdateEverything();
+void ClearSummaryInfo();
#endif
#endif
diff --git a/Editor/editscreen.cpp b/Editor/editscreen.cpp
index 61298070..795304de 100644
--- a/Editor/editscreen.cpp
+++ b/Editor/editscreen.cpp
@@ -73,6 +73,7 @@
#include "Music Control.h"
#include "Soldier Profile.h"
#include "GameSettings.h"
+ #include "Summary Info.h"
#endif
@@ -305,6 +306,9 @@ BOOLEAN EditModeInit( void )
fFirstTimeInEditModeInit = FALSE;
}
+ // Clear the summary info array
+ ClearSummaryInfo();
+
//Initialize editor specific stuff for each Taskbar.
EntryInitEditorTerrainInfo();
EntryInitEditorItemsInfo();
@@ -557,6 +561,9 @@ BOOLEAN EditModeShutdown( void )
HideExitGrids();
+ // Clear the summary info array
+ ClearSummaryInfo();
+
UnPauseGame();
return TRUE;
@@ -581,7 +588,7 @@ void SetBackgroundTexture( )
usIndex = (UINT16)(rand( ) % 10 );
// Adjust for type
- usIndex += gTileTypeStartIndex[ gCurrentBackground ];
+ usIndex = usIndex + gTileTypeStartIndex[ gCurrentBackground ];
// Set land index
if( TypeRangeExistsInLandLayer( cnt, FIRSTFLOOR, LASTFLOOR, &Dummy ) )
@@ -1557,7 +1564,7 @@ void HandleKeyboardShortcuts( )
RemoveAllRoofsOfTypeRange( i, FIRSTTEXTURE, LASTITEM );
RemoveAllOnRoofsOfTypeRange( i, FIRSTTEXTURE, LASTITEM );
RemoveAllShadowsOfTypeRange( i, FIRSTROOF, LASTSLANTROOF );
- usRoofIndex = 9 + ( rand() % 3 );
+ usRoofIndex = (UINT16) (9 + ( rand() % 3 ));
GetTileIndexFromTypeSubIndex( usRoofType, usRoofIndex, &usTileIndex );
AddRoofToHead( i, usTileIndex );
}
@@ -3141,7 +3148,7 @@ void EnsureStatusOfEditorButtons()
void HandleMouseClicksInGameScreen()
{
- EXITGRID dummy={0,0,0,0};
+ //EXITGRID dummy={0,0,0,0};
INT16 sX, sY;
BOOLEAN fPrevState;
if( !GetMouseXY( &sGridX, &sGridY ) )
diff --git a/Path Debug.vsprops b/Path Debug.vsprops
new file mode 100644
index 00000000..bf0b67d0
--- /dev/null
+++ b/Path Debug.vsprops
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/Roof Debug.vsprops b/Roof Debug.vsprops
new file mode 100644
index 00000000..6975c0a4
--- /dev/null
+++ b/Roof Debug.vsprops
@@ -0,0 +1,7 @@
+
+
+
diff --git a/builddefines.h b/builddefines.h
index e5ee732a..3c7de8cf 100644
--- a/builddefines.h
+++ b/builddefines.h
@@ -49,4 +49,6 @@
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NON_CONFORMING_SWPRINTFS
+#include "Profiler.h"
+
#endif
\ No newline at end of file
diff --git a/profiler.cpp b/profiler.cpp
new file mode 100644
index 00000000..0918caba
--- /dev/null
+++ b/profiler.cpp
@@ -0,0 +1,442 @@
+#ifdef PROFILER_ENABLED
+
+#include "builddefines.h"
+#include
+
+#ifdef PERIODIC_PROFILING
+bool gRecordingProfile = false;
+#endif
+
+PerfManager* PerfManager::_instance(NULL);
+
+PerfDatum::PerfDatum( const char* const fileName,
+ const char* const functionName,
+ const int lineNumber,
+ __int64 cycles,
+ __int64 calls)
+ :
+ _fileName(fileName),
+ _functionName(functionName),
+ _lineNumber(lineNumber),
+ _cycles(cycles),
+ _calls(calls)
+{
+}
+
+PerfManager::PerfManager(void)
+ :
+ _callTime(0),
+ _totalTime(0)
+{
+ //Set up a root function so that the stack is never empty:
+ //(this will be the only entry with _lineNumber equal to 0)
+ _perfLog.insert(PerfDatum(__FILE__, "Root",0));
+ _perfStack.push_back(&*(_perfLog.begin()));
+ _lastTime = getCPUCount();
+ calibrate();
+}
+
+void PerfManager::calibrate()
+{
+}
+
+PerfManager::~PerfManager(void)
+{
+}
+
+PerfManager* PerfManager::instance()
+{
+ if(!_instance) //Double-check locking (first check)
+ { _instance = new PerfManager();
+ }
+ return _instance;
+}
+
+void PerfManager::enterFunction(const char* const fileName,
+ const char* const functionName,
+ const int lineNumber)
+{
+ //Mark the time when we end processing the previous function
+ __int64 endTime = getCPUCount();
+ //assuming we haven't corrupted the stack and reduced it to zero elements
+ if(_perfStack.size())
+ { PERF_STACK_T::reverse_iterator lastMarker = _perfStack.rbegin();
+ //Update the total time spent processing the previous function
+ __int64 runTime = (endTime - _lastTime) - _callTime;
+ (**lastMarker)._cycles += runTime;
+ _totalTime += runTime;
+ }
+
+ //If we fail to insert the performance marker into our log, it means it is
+ //a duplicate. We can ignore this "error" as using the existing copy is
+ //the correct behavior.
+ std::pair result =
+ _perfLog.insert(PerfDatum(fileName, functionName, lineNumber));
+ //Update the call count on the new function:
+ PerfDatum* marker = &*(result.first);
+ marker->_calls++;
+ //Add performance marker to the stack as well as the log:
+ _perfStack.push_back(marker);
+ //Now that we are clear of any complex operations, we can set the call
+ //time of the new marker more accurately:
+ _lastTime = getCPUCount();
+}
+
+void PerfManager::exitFunction()
+{
+ //Mark the time when we exited the function
+ __int64 endTime = getCPUCount();
+ //Update the function in our log with its new runtime
+ PERF_STACK_T::reverse_iterator lastMarker = _perfStack.rbegin();
+ __int64 runTime = endTime - _lastTime;
+ (**lastMarker)._cycles += runTime;
+ _totalTime += runTime;
+ _perfStack.pop_back();
+ //Lastly, update the function we've fallen back to with the new current
+ //run time.
+ _lastTime = getCPUCount();
+}
+
+__int64 PerfManager::getCPUCount () const
+{
+ _asm rdtsc
+}
+
+bool PerfSort::operator ()(const PerfDatum& lhs, const PerfDatum&rhs) const
+{
+ if(rhs._lineNumber == lhs._lineNumber)
+ { return 0 < strcmp(rhs._fileName, lhs._fileName);
+ }
+ else
+ { return rhs._lineNumber > lhs._lineNumber;
+ }
+}
+
+bool PerfSort2::operator ()(const PerfDatum& lhs, const PerfDatum&rhs) const
+{
+ return lhs._cycles > rhs._cycles;
+}
+
+int PerfManager::getPercision(const double value) const
+{
+ int retVal = 1;
+ if(10.0 <= value)
+ { retVal = 3;
+ }
+ else if (1.0 <= value)
+ { retVal = 2;
+ }
+ return retVal;
+}
+
+void PerfManager::log(std::ostream &os)
+{
+ //Create a copy of the log that sorts by cycles used
+ std::set logCopy;
+ for(PERF_LOG_T::iterator i = _perfLog.begin(); i != _perfLog.end(); i++)
+ {
+ logCopy.insert(*i);
+ }
+
+ int cyclesWidth = 1;
+ //I want the formatting to be nice!
+ for(std::set::iterator i = logCopy.begin();
+ i != logCopy.end();
+ i++)
+ {
+ if(i->_lineNumber) {
+ std::stringstream cyclesString;
+ cyclesString << i->_cycles;
+ std::string tempString;
+ cyclesString >> tempString;
+ cyclesWidth = tempString.size();
+ break;
+ }
+ }
+
+ //Stream the sorted log to the supplied ostream
+ for(std::set::iterator i = logCopy.begin();
+ i != logCopy.end();
+ ++i)
+ {
+ if(i->_lineNumber)
+ { //Truncate path from file name if the compiler included it.
+ const char* j = i->_fileName + strlen(i->_fileName);
+ while('\\' != *j && '/' != *j && j >= i->_fileName){j--;}
+ if('\\' == *j || '/' == *j){j++;}
+ std::stringstream cyclesString;
+ std::string tempString;
+ cyclesString << i->_cycles;
+ cyclesString >> tempString;
+ os.width(cyclesWidth);
+ os << tempString.c_str() << ", ";
+ __int64 cyclesPerCall = i->_cycles / i->_calls;
+ cyclesString.clear();
+ tempString.clear();
+ cyclesString << cyclesPerCall;
+ cyclesString >> tempString;
+ os.width(cyclesWidth);
+ os << tempString.c_str() << "] cycles (";
+ double percent = double(i->_cycles) / double(_totalTime) * 100;
+ os.precision(getPercision(percent));
+ os.width(4);
+ os << percent << "%) used in [";
+ os.width(8);
+ os << i->_calls << "] calls by " << j << "::" << i->_functionName\
+ << " at line " << i->_lineNumber << std::endl;
+ }
+ }
+}
+
+PerfMarker::PerfMarker( const char* const fileName,
+ const char* const functionName,
+ const int lineNumber)
+ :
+#ifdef PERIODIC_PROFILING
+ _onStack(gRecordingProfile)
+#else
+ _onStack(true)
+#endif
+{
+#ifdef PERIODIC_PROFILING
+ if (gRecordingProfile == true) {
+#endif
+ PerfManager::instance()->enterFunction(fileName,functionName,lineNumber);
+#ifdef PERIODIC_PROFILING
+ }
+#endif
+}
+
+PerfMarker::~PerfMarker()
+{
+ endMark();
+}
+
+void PerfMarker::endMark()
+{
+ if(_onStack)
+ { PerfManager::instance()->exitFunction();
+ _onStack = false;
+ }
+}
+#include "profiler.h"
+#include
+
+#ifdef PERIODIC_PROFILING
+bool gRecordingProfile = false;
+#endif
+
+PerfManager* PerfManager::_instance(NULL);
+
+PerfDatum::PerfDatum( const char* const fileName,
+ const char* const functionName,
+ const int lineNumber,
+ __int64 cycles,
+ __int64 calls)
+ :
+ _fileName(fileName),
+ _functionName(functionName),
+ _lineNumber(lineNumber),
+ _cycles(cycles),
+ _calls(calls)
+{
+}
+
+PerfManager::PerfManager(void)
+ :
+ _callTime(0),
+ _totalTime(0)
+{
+ //Set up a root function so that the stack is never empty:
+ //(this will be the only entry with _lineNumber equal to 0)
+ _perfLog.insert(PerfDatum(__FILE__, "Root",0));
+ _perfStack.push_back(&*(_perfLog.begin()));
+ _lastTime = getCPUCount();
+ calibrate();
+}
+
+void PerfManager::calibrate()
+{
+}
+
+PerfManager::~PerfManager(void)
+{
+}
+
+PerfManager* PerfManager::instance()
+{
+ if(!_instance) //Double-check locking (first check)
+ { _instance = new PerfManager();
+ }
+ return _instance;
+}
+
+void PerfManager::enterFunction(const char* const fileName,
+ const char* const functionName,
+ const int lineNumber)
+{
+ //Mark the time when we end processing the previous function
+ __int64 endTime = getCPUCount();
+ //assuming we haven't corrupted the stack and reduced it to zero elements
+ if(_perfStack.size())
+ { PERF_STACK_T::reverse_iterator lastMarker = _perfStack.rbegin();
+ //Update the total time spent processing the previous function
+ __int64 runTime = (endTime - _lastTime) - _callTime;
+ (**lastMarker)._cycles += runTime;
+ _totalTime += runTime;
+ }
+
+ //If we fail to insert the performance marker into our log, it means it is
+ //a duplicate. We can ignore this "error" as using the existing copy is
+ //the correct behavior.
+ std::pair result =
+ _perfLog.insert(PerfDatum(fileName, functionName, lineNumber));
+ //Update the call count on the new function:
+ PerfDatum* marker = &*(result.first);
+ marker->_calls++;
+ //Add performance marker to the stack as well as the log:
+ _perfStack.push_back(marker);
+ //Now that we are clear of any complex operations, we can set the call
+ //time of the new marker more accurately:
+ _lastTime = getCPUCount();
+}
+
+void PerfManager::exitFunction()
+{
+ //Mark the time when we exited the function
+ __int64 endTime = getCPUCount();
+ //Update the function in our log with its new runtime
+ PERF_STACK_T::reverse_iterator lastMarker = _perfStack.rbegin();
+ __int64 runTime = endTime - _lastTime;
+ (**lastMarker)._cycles += runTime;
+ _totalTime += runTime;
+ _perfStack.pop_back();
+ //Lastly, update the function we've fallen back to with the new current
+ //run time.
+ _lastTime = getCPUCount();
+}
+
+__int64 PerfManager::getCPUCount () const
+{
+ _asm rdtsc
+}
+
+bool PerfSort::operator ()(const PerfDatum& lhs, const PerfDatum&rhs) const
+{
+ if(rhs._lineNumber == lhs._lineNumber)
+ { return 0 < strcmp(rhs._fileName, lhs._fileName);
+ }
+ else
+ { return rhs._lineNumber > lhs._lineNumber;
+ }
+}
+
+bool PerfSort2::operator ()(const PerfDatum& lhs, const PerfDatum&rhs) const
+{
+ return lhs._cycles > rhs._cycles;
+}
+
+int PerfManager::getPercision(const double value) const
+{
+ int retVal = 1;
+ if(10.0 <= value)
+ { retVal = 3;
+ }
+ else if (1.0 <= value)
+ { retVal = 2;
+ }
+ return retVal;
+}
+
+void PerfManager::log(std::ostream &os)
+{
+ //Create a copy of the log that sorts by cycles used
+ std::set logCopy;
+ for(PERF_LOG_T::iterator i = _perfLog.begin(); i != _perfLog.end(); i++)
+ {
+ logCopy.insert(*i);
+ }
+
+ int cyclesWidth = 1;
+ //I want the formatting to be nice!
+ for(std::set::iterator i = logCopy.begin();
+ i != logCopy.end();
+ i++)
+ {
+ if(i->_lineNumber) {
+ std::stringstream cyclesString;
+ cyclesString << i->_cycles;
+ std::string tempString;
+ cyclesString >> tempString;
+ cyclesWidth = tempString.size();
+ break;
+ }
+ }
+
+ //Stream the sorted log to the supplied ostream
+ for(std::set::iterator i = logCopy.begin();
+ i != logCopy.end();
+ ++i)
+ {
+ if(i->_lineNumber)
+ { //Truncate path from file name if the compiler included it.
+ const char* j = i->_fileName + strlen(i->_fileName);
+ while('\\' != *j && '/' != *j && j >= i->_fileName){j--;}
+ if('\\' == *j || '/' == *j){j++;}
+ std::stringstream cyclesString;
+ std::string tempString;
+ cyclesString << i->_cycles;
+ cyclesString >> tempString;
+ os.width(cyclesWidth);
+ os << tempString.c_str() << ", ";
+ __int64 cyclesPerCall = i->_cycles / i->_calls;
+ cyclesString.clear();
+ tempString.clear();
+ cyclesString << cyclesPerCall;
+ cyclesString >> tempString;
+ os.width(cyclesWidth);
+ os << tempString.c_str() << "] cycles (";
+ double percent = double(i->_cycles) / double(_totalTime) * 100;
+ os.precision(getPercision(percent));
+ os.width(4);
+ os << percent << "%) used in [";
+ os.width(8);
+ os << i->_calls << "] calls by " << j << "::" << i->_functionName\
+ << " at line " << i->_lineNumber << std::endl;
+ }
+ }
+}
+
+PerfMarker::PerfMarker( const char* const fileName,
+ const char* const functionName,
+ const int lineNumber)
+ :
+#ifdef PERIODIC_PROFILING
+ _onStack(gRecordingProfile)
+#else
+ _onStack(true)
+#endif
+{
+#ifdef PERIODIC_PROFILING
+ if (gRecordingProfile == true) {
+#endif
+ PerfManager::instance()->enterFunction(fileName,functionName,lineNumber);
+#ifdef PERIODIC_PROFILING
+ }
+#endif
+}
+
+PerfMarker::~PerfMarker()
+{
+ endMark();
+}
+
+void PerfMarker::endMark()
+{
+ if(_onStack)
+ { PerfManager::instance()->exitFunction();
+ _onStack = false;
+ }
+}
+
+#endif
diff --git a/profiler.h b/profiler.h
new file mode 100644
index 00000000..e8e45a1b
--- /dev/null
+++ b/profiler.h
@@ -0,0 +1,87 @@
+#pragma once
+
+#include
+#include
+#include
+
+//#ifndef PROFILER_ENABLED
+//#define PROFILER_ENABLED
+//#endif
+
+#ifdef PROFILER_ENABLED
+#define STRINGIZE(x) #x
+#define NAMED_ PERFORMANCE_MARKER(x) PerfMarker x(__FILE__, STRINGIZE(x), __LINE__);
+#define END_NAMED_ PERFORMANCE_MARKER(x) x.endMark();
+#define PERFORMANCE_MARKER PerfMarker MARK(__FILE__, __FUNCTION__, __LINE__);
+#define PERIODIC_PROFILING
+#else
+#define PERFORMANCE_MARKER
+#endif
+#pragma warning (disable : 4512)//disables assignment operator could not be generated
+
+struct PerfDatum
+{
+ PerfDatum( const char* const fileName,
+ const char* const functionName,
+ const int lineNumber,
+ __int64 cycles = 0,
+ __int64 calls = 0);
+ const char* const _fileName;
+ const char* const _functionName;
+ const int _lineNumber;
+ __int64 _cycles; //Number of CPU cycles used
+ __int64 _calls; //Number of calls to this function
+};
+#pragma warning (default : 4512)//disables assignment operator could not be generated
+
+class PerfSort
+{
+public:
+ bool operator()(const PerfDatum& lhs, const PerfDatum& rhs) const;
+};
+
+class PerfSort2
+{
+public:
+ bool operator()(const PerfDatum& lhs, const PerfDatum& rhs) const;
+};
+
+
+typedef std::set PERF_LOG_T;
+typedef std::vector PERF_STACK_T;
+
+class PerfManager
+{
+public:
+ ~PerfManager(void);
+ static PerfManager* instance();
+ void enterFunction( const char* const fileName,
+ const char* const functionName,
+ const int lineNumber);
+ void exitFunction();
+ void log(std::ostream &os);
+private:
+ PerfManager(void);
+ __int64 getCPUCount(void) const;
+ void calibrate(void);
+ int getPercision(const double value) const; //used for formatting percentages
+ static PerfManager* _instance;
+ PERF_LOG_T _perfLog;
+ PERF_STACK_T _perfStack;
+ __int64 _callTime; //Time it takes to call the getCPUCount function
+ __int64 _totalTime;
+ __int64 _lastTime; //The last time we got hte CPU count.
+};
+
+class PerfMarker
+{
+public:
+ PerfMarker( const char* const fileName,
+ const char* const functionName,
+ const int lineNumber);
+ ~PerfMarker();
+ void endMark();
+private:
+ bool _onStack;
+};
+