From 47727b8b72a02a78cf3c3840118823fedfbe26a3 Mon Sep 17 00:00:00 2001 From: aidinabedi Date: Sun, 13 Dec 2009 13:42:39 +0000 Subject: [PATCH] rewrote the hole shebang to c language! this is extremely untested. --- Shiny_vs2003.sln | 21 -- Shiny_vs2005.sln | 20 -- include/ShinyConfig.h | 29 +- include/ShinyData.h | 114 +++--- include/ShinyDoc.h | 6 +- include/ShinyMacros.h | 44 +-- include/ShinyManager.h | 285 +++++++-------- include/ShinyNode.h | 122 ++++--- include/ShinyNodePool.h | 38 +- include/ShinyOutput.h | 39 +- include/ShinyPrereqs.h | 16 +- include/ShinyTools.h | 41 +-- include/ShinyZone.h | 79 ++-- src/ShinyManager.c | 398 +++++++++++++++++++++ src/ShinyManager.cpp | 391 -------------------- src/ShinyNode.c | 129 +++++++ src/ShinyNode.cpp | 200 ----------- src/{ShinyNodePool.cpp => ShinyNodePool.c} | 54 +-- src/ShinyOutput.c | 152 ++++++++ src/ShinyOutput.cpp | 138 ------- src/ShinyTools.c | 105 ++++++ src/ShinyTools.cpp | 100 ------ src/ShinyZone.c | 171 +++++++++ src/ShinyZone.cpp | 174 --------- src/Shiny_vs2003.vcproj | 171 --------- src/Shiny_vs2005.vcproj | 240 ------------- src/Shiny_vs2008.vcproj | 20 +- 27 files changed, 1398 insertions(+), 1899 deletions(-) delete mode 100644 Shiny_vs2003.sln delete mode 100644 Shiny_vs2005.sln create mode 100644 src/ShinyManager.c delete mode 100644 src/ShinyManager.cpp create mode 100644 src/ShinyNode.c delete mode 100644 src/ShinyNode.cpp rename src/{ShinyNodePool.cpp => ShinyNodePool.c} (54%) create mode 100644 src/ShinyOutput.c delete mode 100644 src/ShinyOutput.cpp create mode 100644 src/ShinyTools.c delete mode 100644 src/ShinyTools.cpp create mode 100644 src/ShinyZone.c delete mode 100644 src/ShinyZone.cpp delete mode 100644 src/Shiny_vs2003.vcproj delete mode 100644 src/Shiny_vs2005.vcproj diff --git a/Shiny_vs2003.sln b/Shiny_vs2003.sln deleted file mode 100644 index 468cb74..0000000 --- a/Shiny_vs2003.sln +++ /dev/null @@ -1,21 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shiny", "src\Shiny_vs2003.vcproj", "{063905E0-A6AC-445A-AF5A-572E62B73F63}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {063905E0-A6AC-445A-AF5A-572E62B73F63}.Debug.ActiveCfg = Debug|Win32 - {063905E0-A6AC-445A-AF5A-572E62B73F63}.Debug.Build.0 = Debug|Win32 - {063905E0-A6AC-445A-AF5A-572E62B73F63}.Release.ActiveCfg = Release|Win32 - {063905E0-A6AC-445A-AF5A-572E62B73F63}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/Shiny_vs2005.sln b/Shiny_vs2005.sln deleted file mode 100644 index b13e077..0000000 --- a/Shiny_vs2005.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shiny", "src\Shiny_vs2005.vcproj", "{D44CCFEB-7FC2-46E6-8290-E0B00D06A636}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D44CCFEB-7FC2-46E6-8290-E0B00D06A636}.Debug|Win32.ActiveCfg = Debug|Win32 - {D44CCFEB-7FC2-46E6-8290-E0B00D06A636}.Debug|Win32.Build.0 = Debug|Win32 - {D44CCFEB-7FC2-46E6-8290-E0B00D06A636}.Release|Win32.ActiveCfg = Release|Win32 - {D44CCFEB-7FC2-46E6-8290-E0B00D06A636}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/include/ShinyConfig.h b/include/ShinyConfig.h index 6546d15..4b35a7b 100644 --- a/include/ShinyConfig.h +++ b/include/ShinyConfig.h @@ -27,16 +27,33 @@ applications, and to alter it and redistribute it freely, subject to the followi //----------------------------------------------------------------------------- -#ifndef SHINY_PROFILER -#define SHINY_PROFILER TRUE +// SHINY_COMPILED is the master on or off swith at compile time. Define it to TRUE or FALSE before including header Shiny.h or inside ShinyConfig.h. Default is TRUE. +#ifndef SHINY_COMPILED +#define SHINY_COMPILED TRUE #endif -#ifndef SHINY_PROFILER_LOOKUPRATE -#define SHINY_PROFILER_LOOKUPRATE FALSE +// if SHINY_LOOKUP_RATE is defined to TRUE then Shiny will record the success of its hash function. This is useful for debugging. Default is FALSE. +#ifndef SHINY_LOOKUP_RATE +#define SHINY_LOOKUP_RATE FALSE #endif -#ifndef SHINY_PROFILER_HASENABLED -#define SHINY_PROFILER_HASENABLED FALSE +// if SHINY_HAS_ENABLED is defined to TRUE then Shiny can be enabled and disabled at runtime. TODO: bla bla... +#ifndef SHINY_HAS_ENABLED +#define SHINY_HAS_ENABLED FALSE +#endif + +// TODO: +#define SHINY_OUTPUT_MODE_FLAT 0x1 + +// TODO: +#define SHINY_OUTPUT_MODE_TREE 0x2 + +// TODO: +#define SHINY_OUTPUT_MODE_BOTH 0x3 + +// TODO: +#ifndef SHINY_OUTPUT_MODE +#define SHINY_OUTPUT_MODE SHINY_OUTPUT_MODE_BOTH #endif diff --git a/include/ShinyData.h b/include/ShinyData.h index 847bea4..66fe43b 100644 --- a/include/ShinyData.h +++ b/include/ShinyData.h @@ -26,66 +26,68 @@ applications, and to alter it and redistribute it freely, subject to the followi #include "ShinyPrereqs.h" -namespace Shiny { - - -//----------------------------------------------------------------------------- - - struct ProfileLastData { - uint32_t entryCount; - tick_t selfTicks; - }; - - //----------------------------------------------------------------------------- - struct ProfileData { - - template - struct Data { - T cur; - float avg; - - void computeAverage(float a_damping) { avg = a_damping * (avg - cur) + cur; } - void copyAverage(void) { avg = (float) cur; } - void clear(void) { cur = 0; avg = 0; } - }; - +typedef struct { + uint32_t entryCount; + tick_t selfTicks; +} ShinyLastData; - Data entryCount; - Data selfTicks; - Data childTicks; - - - tick_t totalTicksCur(void) const { return selfTicks.cur + childTicks.cur; } - float totalTicksAvg(void) const { return selfTicks.avg + childTicks.avg; } - - void computeAverage(float a_damping) { - entryCount.computeAverage(a_damping); - selfTicks.computeAverage(a_damping); - childTicks.computeAverage(a_damping); - } - - void copyAverage(void) { - entryCount.copyAverage(); - selfTicks.copyAverage(); - childTicks.copyAverage(); - } - - void clearAll(void) { - entryCount.clear(); - selfTicks.clear(); - childTicks.clear(); - } - - void clearCurrent(void) { - entryCount.cur = 0; - selfTicks.cur = 0; - childTicks.cur = 0; - } - }; +//----------------------------------------------------------------------------- -} // namespace Shiny +typedef struct { + tick_t cur; + float avg; +} ShinyTickData; + +typedef struct { + uint32_t cur; + float avg; +} ShinyCountData; + +typedef struct { + ShinyCountData entryCount; + ShinyTickData selfTicks; + ShinyTickData childTicks; +} ShinyData; + +SHINY_INLINE tick_t ShinyData_totalTicksCur(const ShinyData *self) { + return self->selfTicks.cur + self->childTicks.cur; +} + +SHINY_INLINE float ShinyData_totalTicksAvg(const ShinyData *self) { + return self->selfTicks.avg + self->childTicks.avg; +} + +SHINY_INLINE void ShinyData_computeAverage(ShinyData *self, float a_damping) { + self->entryCount.avg = self->entryCount.cur + + a_damping * (self->entryCount.avg - self->entryCount.cur); + self->selfTicks.avg = self->selfTicks.cur + + a_damping * (self->selfTicks.avg - self->selfTicks.cur); + self->childTicks.avg = self->childTicks.cur + + a_damping * (self->childTicks.avg - self->childTicks.cur); +} + +SHINY_INLINE void ShinyData_copyAverage(ShinyData *self) { + self->entryCount.avg = (float) self->entryCount.cur; + self->selfTicks.avg = (float) self->selfTicks.cur; + self->childTicks.avg = (float) self->childTicks.cur; +} + +SHINY_INLINE void ShinyData_clearAll(ShinyData *self) { + self->entryCount.cur = 0; + self->entryCount.avg = 0; + self->selfTicks.cur = 0; + self->selfTicks.avg = 0; + self->childTicks.cur = 0; + self->childTicks.avg = 0; +} + +SHINY_INLINE void ShinyData_clearCurrent(ShinyData *self) { + self->entryCount.cur = 0; + self->selfTicks.cur = 0; + self->childTicks.cur = 0; +} #endif // ifndef SHINY_*_H diff --git a/include/ShinyDoc.h b/include/ShinyDoc.h index bd88112..ebc402b 100644 --- a/include/ShinyDoc.h +++ b/include/ShinyDoc.h @@ -21,7 +21,7 @@ applications, and to alter it and redistribute it freely, subject to the followi 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SHINY_PROFILER // do not include this file +#ifndef SHINY_COMPILED // do not include this file //----------------------------------------------------------------------------- @@ -38,7 +38,7 @@ Shiny is a low overhead, well documented and lightning fast C++ profiler. Easy t \n \subsection sub-1 What is this document? -\ref ShinyDoc.h is a complete description of all the Shiny macros. Macro is a preprocessor directive that provides a mechanism for token replacement in your source code. Shiny uses macros to simplify interface and remain powerful. If the preprocessor SHINY_PROFILER is FALSE macro is ignored unless specified otherwise. +\ref ShinyDoc.h is a complete description of all the Shiny macros. Macro is a preprocessor directive that provides a mechanism for token replacement in your source code. Shiny uses macros to simplify interface and remain powerful. If the preprocessor SHINY_COMPILED is FALSE macro is ignored unless specified otherwise. \n \subsection sub2 Why did you create Shiny? @@ -68,7 +68,7 @@ Where are some key features: \n \subsection sub5 How to switch Shiny on and off? -Shiny is turned on or off at compile time. Define the pre-processor SHINY_PROFILER to TRUE or FALSE to enable or disable, before including header Shiny.h. Shiny can also be enabled or disabled in ShinyConfig.h. Default is on. +Shiny is turned on or off at compile time. Define the pre-processor SHINY_COMPILED to TRUE or FALSE to enable or disable, before including header Shiny.h. Shiny can also be enabled or disabled in ShinyConfig.h. Default is on. \n \subsection sub6 Does Shiny support C language? diff --git a/include/ShinyMacros.h b/include/ShinyMacros.h index 5d87108..c6add6a 100644 --- a/include/ShinyMacros.h +++ b/include/ShinyMacros.h @@ -26,46 +26,46 @@ applications, and to alter it and redistribute it freely, subject to the followi #include "ShinyManager.h" -#if SHINY_PROFILER == TRUE +#if SHINY_COMPILED == TRUE //----------------------------------------------------------------------------- // public preprocessors #define PROFILE_UPDATE_ALL \ - Shiny::ProfileManager::instance.update + Shiny::ShinyManager::instance.update #define PROFILE_OUTPUT_ALL \ - Shiny::ProfileManager::instance.output + Shiny::ShinyManager::instance.output #define PROFILE_GET_TREE_OUTPUT() \ - Shiny::ProfileManager::instance.outputNodesAsString() + Shiny::ShinyManager::instance.outputNodesAsString() #define PROFILE_GET_FLAT_OUTPUT() \ - Shiny::ProfileManager::instance.outputZonesAsString() + Shiny::ShinyManager::instance.outputZonesAsString() #define PROFILE_DESTROY_ALL() \ - Shiny::ProfileManager::instance.destroy() + Shiny::ShinyManager::instance.destroy() #define PROFILE_CLEAR() \ - Shiny::ProfileManager::instance.clear() + Shiny::ShinyManager::instance.clear() #define PROFILE_SORT_ZONES() \ - Shiny::ProfileManager::instance.sortZones() + Shiny::ShinyManager::instance.sortZones() //----------------------------------------------------------------------------- // public preprocessor #define PROFILE_GET_ROOT_DATA() \ - Shiny::ProfileManager::instance.rootZone.data + Shiny::ShinyManager::instance.rootZone.data //----------------------------------------------------------------------------- // public preprocessor #define PROFILE_END() \ - Shiny::ProfileManager::instance._endCurNode() + ShinyManager_endCurNode(Shiny_instance) //----------------------------------------------------------------------------- @@ -160,9 +160,9 @@ applications, and to alter it and redistribute it freely, subject to the followi //----------------------------------------------------------------------------- // public preprocessor -#if SHINY_PROFILER_HASENABLED == TRUE +#if SHINY_HAS_ENABLED == TRUE #define PROFILE_SET_ENABLED( boolean ) \ - Shiny::ProfileManager::instance.enabled = boolean + Shiny::ShinyManager::instance.enabled = boolean #endif @@ -181,8 +181,8 @@ applications, and to alter it and redistribute it freely, subject to the followi #define _PROFILE_ZONE_DEFINE( id, string ) \ \ - Shiny::ProfileZone id = { \ - NULL, Shiny::ProfileZone::STATE_HIDDEN, string, \ + Shiny::ShinyZone id = { \ + NULL, SHINY_ZONE_STATE_HIDDEN, string, \ { { 0, 0 }, { 0, 0 }, { 0, 0 } } \ } @@ -192,7 +192,7 @@ applications, and to alter it and redistribute it freely, subject to the followi #define _PROFILE_ZONE_DECLARE( prefix, id ) \ \ - prefix Shiny::ProfileZone id + prefix Shiny::ShinyZone id //----------------------------------------------------------------------------- @@ -200,7 +200,7 @@ applications, and to alter it and redistribute it freely, subject to the followi #define _PROFILE_BLOCK_DEFINE( id ) \ \ - Shiny::ProfileAutoEndNode SHINY_UNUSED id + Shiny::ShinyEndNodeOnDestruction SHINY_UNUSED id //----------------------------------------------------------------------------- @@ -209,19 +209,19 @@ applications, and to alter it and redistribute it freely, subject to the followi #define _PROFILE_ZONE_BEGIN( id ) \ { \ static Shiny::ProfileNodeCache cache = \ - &Shiny::ProfileNode::_dummy; \ + &ShinyNode_dummy; \ \ - Shiny::ProfileManager::instance._beginNode(&cache, &id); \ + ShinyManager_lookupAndBeginNode(Shiny_instance, &cache, &id); \ } //----------------------------------------------------------------------------- -#else // #if SHINY_PROFILER == TRUE +#else // #if SHINY_COMPILED == TRUE namespace Shiny { - SHINY_INLINE ProfileData GetEmptyData() { - ProfileData a = { { 0, 0 }, { 0, 0 }, { 0, 0 } }; + SHINY_INLINE ShinyData GetEmptyData() { + ShinyData a = { { 0, 0 }, { 0, 0 }, { 0, 0 } }; return a; } } @@ -244,7 +244,7 @@ namespace Shiny { #define PROFILE_GET_SHARED_DATA(name) Shiny::GetEmptyData() #define PROFILE_GET_ROOT_DATA() Shiny::GetEmptyData() -#if SHINY_PROFILER_HASENABLED == TRUE +#if SHINY_HAS_ENABLED == TRUE #define PROFILE_SET_ENABLED(boolean) #endif diff --git a/include/ShinyManager.h b/include/ShinyManager.h index 2fe22d7..4682021 100644 --- a/include/ShinyManager.h +++ b/include/ShinyManager.h @@ -30,231 +30,198 @@ applications, and to alter it and redistribute it freely, subject to the followi #include "ShinyTools.h" #include "ShinyOutput.h" -#include +#include - -#if SHINY_PROFILER == TRUE -namespace Shiny { +#if SHINY_COMPILED == TRUE //----------------------------------------------------------------------------- - struct ProfileManager { - //NOTE: data-members are intentionally public because the - // class needs to fulfil the definition of an aggregate - - enum TABLE_SIZE { - TABLE_SIZE_INIT = 256 - }; +typedef struct { + //NOTE: data-members are intentionally public because the + // class needs to fulfil the definition of an aggregate -#if SHINY_PROFILER_HASENABLED == TRUE - bool enabled; +#if SHINY_HAS_ENABLED == TRUE + bool enabled; #endif - tick_t _lastTick; + tick_t _lastTick; - ProfileNode* _curNode; + ShinyNode* _curNode; - uint32_t _tableMask; // = _tableSize - 1 + uint32_t _tableMask; // = _tableSize - 1 - ProfileNodeTable* _nodeTable; + ProfileNodeTable* _nodeTable; -#if SHINY_PROFILER_LOOKUPRATE == TRUE - uint64_t _lookupCount; - uint64_t _lookupSuccessCount; +#if SHINY_LOOKUP_RATE == TRUE + uint64_t _lookupCount; + uint64_t _lookupSuccessCount; #endif - uint32_t _tableSize; - - uint32_t nodeCount; - uint32_t zoneCount; - - ProfileZone* _lastZone; - - ProfileNodePool* _lastNodePool; - ProfileNodePool* _firstNodePool; + uint32_t _tableSize; - ProfileNode rootNode; - ProfileZone rootZone; + uint32_t nodeCount; + uint32_t zoneCount; - bool _initialized; - bool _firstUpdate; + ShinyZone* _lastZone; - static ProfileNode* _dummyNodeTable[]; + ShinyNodePool* _lastNodePool; + ShinyNodePool* _firstNodePool; - static ProfileManager instance; + ShinyNode rootNode; + ShinyZone rootZone; - // + int _initialized; + int _firstUpdate; +} ShinyManager; - SHINY_INLINE void _appendTicksToCurNode(void) { - register tick_t curTick; - GetTicks(&curTick); - _curNode->appendTicks(curTick - _lastTick); - _lastTick = curTick; - } +//----------------------------------------------------------------------------- - ProfileNode* _lookupNode(ProfileNodeCache* a_cache, ProfileZone* a_zone); +extern ShinyNode* ShinyManager_dummyNodeTable[]; - void _createNodeTable(uint32_t a_count); - void _resizeNodeTable(uint32_t a_count); +extern ShinyManager Shiny_instance; - void _createNodePool(uint32_t a_count); - void _resizeNodePool(uint32_t a_count); - ProfileNode* _createNode(ProfileNodeCache* a_cache, ProfileZone* a_pZone); - void _insertNode(ProfileNode* a_pNode); +//----------------------------------------------------------------------------- - void _init(void) { - _initialized = true; +SHINY_INLINE void _ShinyManager_appendTicksToCurNode(ShinyManager *self) { + tick_t curTick; + ShinyGetTicks(&curTick); - rootNode._last.entryCount = 1; - rootNode._last.selfTicks = 0; - GetTicks(&_lastTick); - } + ShinyNode_appendTicks(self->_curNode, curTick - self->_lastTick); + self->_lastTick = curTick; +} - void _uninit(void) { - _initialized = false; +ShinyNode* _ShinyManager_lookupNode(ShinyManager *self, ProfileNodeCache* a_cache, ShinyZone* a_zone); - rootNode.clear(); - rootNode.parent = &rootNode; - rootNode.zone = &rootZone; - } +void _ShinyManager_createNodeTable(ShinyManager *self, uint32_t a_count); +void _ShinyManager_resizeNodeTable(ShinyManager *self, uint32_t a_count); -#if SHINY_PROFILER_LOOKUPRATE == TRUE - SHINY_INLINE void _incLookup(void) { _lookupCount++; } - SHINY_INLINE void _incLookupSuccess(void) { _lookupSuccessCount++; } - SHINY_INLINE float getLookupRate(void) const { return ((float) _lookupSuccessCount) / ((float) _lookupCount); } +void _ShinyManager_createNodePool(ShinyManager *self, uint32_t a_count); +void _ShinyManager_resizeNodePool(ShinyManager *self, uint32_t a_count); -#else - SHINY_INLINE void _incLookup(void) {} - SHINY_INLINE void _incLookupSuccess(void) {} - SHINY_INLINE float getLookupRate(void) const { return -1; } -#endif +ShinyNode* _ShinyManager_createNode(ShinyManager *self, ProfileNodeCache* a_cache, ShinyZone* a_pZone); +void _ShinyManager_insertNode(ShinyNode* a_pNode); - void _resetZones(void); - void _destroyNodes(void); +SHINY_INLINE void _ShinyManager_init(ShinyManager *self) { + self->_initialized = TRUE; - SHINY_INLINE float tableUsage(void) const { return ((float) nodeCount) / ((float) _tableSize); } + self->rootNode._last.entryCount = 1; + self->rootNode._last.selfTicks = 0; + ShinyGetTicks(&self->_lastTick); +} - uint32_t staticMemInBytes(void) { - // ASSUME: zones and cache are used as intended; throught the macros +SHINY_INLINE void _ShinyManager_uninit(ShinyManager *self) { + self->_initialized = FALSE; - return sizeof(this) + sizeof(_dummyNodeTable[0]) + sizeof(ProfileNode::_dummy) - + (zoneCount - 1) * (sizeof(ProfileZone) + sizeof(ProfileNodeCache)); - } + ShinyNode_clear(&self->rootNode); + self->rootNode.parent = &self->rootNode; + self->rootNode.zone = &self->rootZone; +} - uint32_t allocMemInBytes(void) { - return _tableSize * sizeof(ProfileNode*) - + (_firstNodePool)? _firstNodePool->memoryUsageChain() : 0; - } +#if SHINY_LOOKUP_RATE == TRUE +SHINY_INLINE void _ShinyManager_incLookup(ShinyManager *self) { self->_lookupCount++; } +SHINY_INLINE void _ShinyManager_incLookupSuccess(ShinyManager *self) { self->_lookupSuccessCount++; } +SHINY_INLINE float ShinyManager_getLookupRate(const ShinyManager *self) { return ((float) self->_lookupSuccessCount) / ((float) self->_lookupCount); } - SHINY_INLINE void _beginNode(ProfileNodeCache* a_cache, ProfileZone* a_zone) { -#if SHINY_PROFILER_HASENABLED == TRUE - if (!enabled) return; +#else +SHINY_INLINE void _ShinyManager_incLookup(ShinyManager *self) {} +SHINY_INLINE void _ShinyManager_incLookupSuccess(ShinyManager *self) {} +SHINY_INLINE float ShinyManager_getLookupRate(const ShinyManager *self) { return -1; } #endif - if (_curNode != (*a_cache)->parent) - *a_cache = _lookupNode(a_cache, a_zone); +void ShinyManager_resetZones(ShinyManager *self); +void ShinyManager_destroyNodes(ShinyManager *self); - _beginNode(*a_cache); - } +SHINY_INLINE float ShinyManager_tableUsage(const ShinyManager *self) { + return ((float) self->nodeCount) / ((float) self->_tableSize); +} - SHINY_INLINE void _beginNode(ProfileNode* a_node) { -#if SHINY_PROFILER_HASENABLED == TRUE - if (!enabled) return; -#endif +SHINY_INLINE uint32_t ShinyManager_allocMemInBytes(const ShinyManager *self) { + return self->_tableSize * sizeof(ShinyNode*) + + (self->_firstNodePool)? ShinyNodePool_memoryUsageChain(self->_firstNodePool) : 0; +} - a_node->beginEntry(); +SHINY_INLINE void ShinyManager_beginNode(ShinyManager *self, ShinyNode* a_node) { + ShinyNode_beginEntry(a_node); - _appendTicksToCurNode(); - _curNode = a_node; - } + _ShinyManager_appendTicksToCurNode(self); + self->_curNode = a_node; +} - SHINY_INLINE void _endCurNode(void) { -#if SHINY_PROFILER_HASENABLED == TRUE - if (!enabled) return; +SHINY_INLINE void ShinyManager_lookupAndBeginNode(ShinyManager *self, ProfileNodeCache* a_cache, ShinyZone* a_zone) { +#if SHINY_HAS_ENABLED == TRUE + if (!self->enabled) return; #endif - _appendTicksToCurNode(); - _curNode = _curNode->parent; - } - - // - - void preLoad(void); - - void updateClean(void); - void update(float a_damping = 0.9f); + if (self->_curNode != (*a_cache)->parent) + *a_cache = _ShinyManager_lookupNode(self, a_cache, a_zone); - void clear(void); - void destroy(void); + ShinyManager_beginNode(self, *a_cache); +} - bool output(const char *a_filename); - bool output(std::ostream &a_ostream = std::cout); - - SHINY_INLINE std::string outputNodesAsString(void) { - return OutputNodesAsString(&rootNode, nodeCount); - } +SHINY_INLINE void ShinyManager_endCurNode(ShinyManager *self) { +#if SHINY_HAS_ENABLED == TRUE + if (!enabled) return; +#endif - SHINY_INLINE std::string outputZonesAsString(void) { - return OutputZonesAsString(&rootZone, zoneCount); - } + _ShinyManager_appendTicksToCurNode(self); + self->_curNode = self->_curNode->parent; +} - void sortZones(void) { - if (rootZone.next) - rootZone.next = rootZone.next->sortChain(); - } +// - // +void ShinyManager_preLoad(ShinyManager *self); - void enumerateNodes(void (*a_func)(const ProfileNode*)) { enumerateNodes(a_func, &rootNode); } - template void enumerateNodes(T* a_this, void (T::*a_func)(const ProfileNode*)) { enumerateNodes(a_this, a_func, &rootNode); } - void enumerateZones(void (*a_func)(const ProfileZone*)) { enumerateZones(a_func, &rootZone); } - template void enumerateZones(T* a_this, void (T::*a_func)(const ProfileZone*)) { enumerateZones(a_this, a_func, &rootZone); } +void ShinyManager_updateClean(ShinyManager *self); +void ShinyManager_update(ShinyManager *self, float a_damping); - static void enumerateNodes(void (*a_func)(const ProfileNode*), const ProfileNode* a_node) { - a_func(a_node); +void ShinyManager_clear(ShinyManager *self); +void ShinyManager_destroy(ShinyManager *self); - if (a_node->firstChild) enumerateNodes(a_func, a_node->firstChild); - if (a_node->nextSibling) enumerateNodes(a_func, a_node->nextSibling); - } +SHINY_INLINE void ShinyManager_sortZones(ShinyManager *self) { + if (self->rootZone.next) + self->rootZone.next = ShinyZone_sortChain(self->rootZone.next); +} - template - static void enumerateNodes(T* a_this, void (T::*a_func)(const ProfileNode*), const ProfileNode* a_node) { - (a_this->*a_func)(a_node); +// - if (a_node->firstChild) enumerateNodes(a_this, a_func, a_node->firstChild); - if (a_node->nextSibling) enumerateNodes(a_this, a_func, a_node->nextSibling); - } +SHINY_INLINE void ShinyManager_enumerateNodes(ShinyManager *self, void (*a_func)(const ShinyNode*)) { + ShinyNode_enumerateNodes(&self->rootNode, a_func); +} - static void enumerateZones(void (*a_func)(const ProfileZone*), const ProfileZone* a_zone) { - a_func(a_zone); +SHINY_INLINE void ShinyManager_enumerateZones(ShinyManager *self, void (*a_func)(const ShinyZone*)) { + ShinyZone_enumerateZones(&self->rootZone, a_func); +} - if (a_zone->next) enumerateZones(a_func, a_zone->next); - } +#if __cplusplus +template void ShinyManager_enumerateNodes(ShinyManager *self, T* a_this, void (T::*a_func)(const ShinyNode*)) { + ShinyNode_enumerateNodes(&self->rootNode, a_this, a_func); +} - template - static void enumerateZones(T* a_this, void (T::*a_func)(const ProfileZone*), const ProfileZone* a_zone) { - (a_this->*a_func)(a_zone); +template void ShinyManager_enumerateZones(ShinyManager *self, T* a_this, void (T::*a_func)(const ShinyZone*)) { + ShinyZone_enumerateZones(&self->rootZone, a_this, a_func); +} +#endif - if (a_zone->next) enumerateZones(a_this, a_func, a_zone->next); - } - }; +int ShinyManager_outputToFile(ShinyManager *self, const char *a_filename); +void ShinyManager_outputToStream(ShinyManager *self, FILE *stream); //----------------------------------------------------------------------------- - class ProfileAutoEndNode { - public: +#if __cplusplus +class ShinyEndNodeOnDestruction { +public: - SHINY_INLINE ~ProfileAutoEndNode() { - ProfileManager::instance._endCurNode(); - } - }; + SHINY_INLINE ~ShinyEndNodeOnDestruction() { + ShinyManager_endCurNode(&Shiny_instance); + } +}; +#endif -} // namespace Shiny -#endif // if SHINY_PROFILER == TRUE +#endif // if SHINY_COMPILED == TRUE #endif // ifndef SHINY_*_H diff --git a/include/ShinyNode.h b/include/ShinyNode.h index 9a36483..af14a16 100644 --- a/include/ShinyNode.h +++ b/include/ShinyNode.h @@ -27,82 +27,106 @@ applications, and to alter it and redistribute it freely, subject to the followi #include "ShinyData.h" #include "ShinyTools.h" -#if SHINY_PROFILER == TRUE -namespace Shiny { +#if SHINY_COMPILED == TRUE //----------------------------------------------------------------------------- - struct ProfileNode { +typedef struct _ShinyNode { - //NOTE: data-members are intentionally public because the - // class needs to fulfil the definition of an aggregate + ShinyLastData _last; + struct _ShinyZone* zone; + struct _ShinyNode* parent; + struct _ShinyNode* nextSibling; - ProfileLastData _last; + struct _ShinyNode* firstChild; + struct _ShinyNode* lastChild; - ProfileZone* zone; - ProfileNode* parent; - ProfileNode* nextSibling; + uint32_t childCount; + uint32_t entryLevel; - ProfileNode* firstChild; - ProfileNode* lastChild; + ProfileNodeCache* _cache; - uint32_t childCount; - uint32_t entryLevel; + ShinyData data; - ProfileNodeCache* _cache; + // +} ShinyNode; - ProfileData data; - static ProfileNode _dummy; +//----------------------------------------------------------------------------- + +extern ShinyNode ShinyNode_dummy; + + +//----------------------------------------------------------------------------- + +SHINY_INLINE void ShinyNode_addChild(ShinyNode* self, ShinyNode* a_child) { + if (self->childCount++) { + self->lastChild->nextSibling = a_child; + self->lastChild = a_child; + + } else { + self->lastChild = a_child; + self->firstChild = a_child; + } +} + +SHINY_INLINE void ShinyNode_init(ShinyNode* self, ShinyNode* a_parent, struct _ShinyZone* a_zone, ProfileNodeCache* a_cache) { + // NOTE: all member variables are assumed to be zero when allocated + + self->zone = a_zone; + self->parent = a_parent; - // + self->entryLevel = a_parent->entryLevel + 1; + ShinyNode_addChild(a_parent, self); - void init(ProfileNode* a_parent, ProfileZone* a_zone, ProfileNodeCache* a_cache) { - // NOTE: all member variables are assumed to be zero when allocated + self->_cache = a_cache; +} - zone = a_zone; - parent = a_parent; +void ShinyNode_updateTree(ShinyNode* self, float a_damping); +void ShinyNode_updateTreeSimple(ShinyNode* self); - entryLevel = a_parent->entryLevel + 1; - a_parent->addChild(this); +SHINY_INLINE void ShinyNode_destroy(ShinyNode* self) { + *(self->_cache) = &ShinyNode_dummy; +} - _cache = a_cache; - } +SHINY_INLINE void ShinyNode_appendTicks(ShinyNode* self, tick_t a_elapsedTicks) { + self->_last.selfTicks += a_elapsedTicks; +} - void addChild(ProfileNode* a_child) { - if (childCount++) { - lastChild->nextSibling = a_child; - lastChild = a_child; +SHINY_INLINE void ShinyNode_beginEntry(ShinyNode* self) { + self->_last.entryCount++; +} - } else { - lastChild = a_child; - firstChild = a_child; - } - } +SHINY_INLINE int ShinyNode_isRoot(ShinyNode* self) { + return (self->entryLevel == 0); +} - void updateTree(float a_damping); - void updateTree(void); +SHINY_INLINE int ShinyNode_isDummy(ShinyNode* self) { + return (self == &ShinyNode_dummy); +} - void destroy(void) { *_cache = &_dummy; } +SHINY_INLINE int ShinyNode_isEqual(ShinyNode* self, const ShinyNode* a_parent, const struct _ShinyZone* a_zone) { + return (self->parent == a_parent && self->zone == a_zone); +} - SHINY_INLINE void appendTicks(tick_t a_elapsedTicks) { _last.selfTicks += a_elapsedTicks; } - SHINY_INLINE void beginEntry(void) { _last.entryCount++; } +const ShinyNode* ShinyNode_findNextInTree(const ShinyNode* self); - bool isRoot(void) const { return (entryLevel == 0); } - bool isDummy(void) const { return (this == &_dummy); } +void ShinyNode_clear(ShinyNode* self); - bool isEqual(const ProfileNode* a_parent, const ProfileZone* a_zone) const { - return (parent == a_parent && zone == a_zone); - } +void ShinyNode_enumerateNodes(const ShinyNode* a_node, void (*a_func)(const ShinyNode*)); - const ProfileNode* findNextInTree(void) const; +#if __cplusplus +template +void ShinyNode_enumerateNodes(const ShinyNode* a_node, T* a_this, void (T::*a_func)(const ShinyNode*)) { + (a_this->*a_func)(a_node); - void clear(void); - }; + if (a_node->firstChild) ShinyNode_enumerateNodes(a_node->firstChild, a_this, a_func); + if (a_node->nextSibling) ShinyNode_enumerateNodes(a_node->nextSibling, a_this, a_func); +} +#endif -} // namespace Shiny -#endif // if SHINY_PROFILER == TRUE +#endif // if SHINY_COMPILED == TRUE #endif // ifndef SHINY_*_H diff --git a/include/ShinyNodePool.h b/include/ShinyNodePool.h index 671d229..43a9d83 100644 --- a/include/ShinyNodePool.h +++ b/include/ShinyNodePool.h @@ -26,35 +26,39 @@ applications, and to alter it and redistribute it freely, subject to the followi #include "ShinyNode.h" -#if SHINY_PROFILER == TRUE -namespace Shiny { +#if SHINY_COMPILED == TRUE //----------------------------------------------------------------------------- - struct ProfileNodePool { +typedef struct _ShinyNodePool { - typedef ProfileNode T; + struct _ShinyNodePool* nextPool; - ProfileNodePool* nextPool; + ShinyNode *_nextItem; + ShinyNode *endOfItems; - T *_nextItem; - T *endOfItems; + ShinyNode _items[1]; - T _items[1]; +} ShinyNodePool; - T* firstItem(void) { return &_items[0]; } - T* newItem(void) { return _nextItem++; } - const T* unusedItem(void) const { return _nextItem; } +//----------------------------------------------------------------------------- + +SHINY_INLINE ShinyNode* ShinyNodePool_firstItem(ShinyNodePool *self) { + return &(self->_items[0]); +} + +SHINY_INLINE ShinyNode* ShinyNodePool_newItem(ShinyNodePool *self) { + return self->_nextItem++; +} + +ShinyNodePool* ShinyNodePool_create(uint32_t a_items); +void ShinyNodePool_destroy(ShinyNodePool *self); - static ProfileNodePool* createNodePool(uint32_t a_items); +uint32_t ShinyNodePool_memoryUsageChain(ShinyNodePool *first); - uint32_t memoryUsageChain(void); - void destroy(void); - }; -} // namespace Shiny -#endif // if SHINY_PROFILER == TRUE +#endif // if SHINY_COMPILED == TRUE #endif // ifndef SHINY_*_H diff --git a/include/ShinyOutput.h b/include/ShinyOutput.h index 1739307..510b7a6 100644 --- a/include/ShinyOutput.h +++ b/include/ShinyOutput.h @@ -27,31 +27,38 @@ applications, and to alter it and redistribute it freely, subject to the followi #include "ShinyNode.h" #include "ShinyZone.h" -#include - -#if SHINY_PROFILER == TRUE -namespace Shiny { +#if SHINY_COMPILED == TRUE //----------------------------------------------------------------------------- - enum OUTPUT_WIDTH { - OUTPUT_WIDTH_CALL = 6, - OUTPUT_WIDTH_TIME = 6, - OUTPUT_WIDTH_PERC = 4, - OUTPUT_WIDTH_SUM = 79, +int ShinyPrintNodesSize(uint32_t a_count); +int ShinyPrintZonesSize(uint32_t a_count); - OUTPUT_WIDTH_DATA = 1+OUTPUT_WIDTH_CALL + 1 + 2*(OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1) + 1, - OUTPUT_WIDTH_NAME = OUTPUT_WIDTH_SUM - OUTPUT_WIDTH_DATA - }; +void ShinyPrintNodes(char* output, const ShinyNode *a_root); +void ShinyPrintZones(char* output, const ShinyZone *a_root); //----------------------------------------------------------------------------- - std::string OutputNodesAsString(const ProfileNode *a_root, uint32_t a_count); - std::string OutputZonesAsString(const ProfileZone *a_root, uint32_t a_count); +#if __cplusplus +#include + +/* +SHINY_INLINE std::string ShinyNodesToString(const ShinyNode *a_root, uint32_t a_count) { + std::string str(ShinyPrintNodesSize(a_count) - 1); + ShinyPrintNodes(&str[0], a_root); + return str; +} + +SHINY_INLINE std::string ShinyZonesToString(const ShinyZone *a_root, uint32_t a_count) { + std::string str(ShinyPrintZonesSize(a_count) - 1); + ShinyPrintZones(&str[0], a_root); + return str; +} +*/ +#endif -} // namespace Shiny -#endif // if SHINY_PROFILER == TRUE +#endif // if SHINY_COMPILED == TRUE #endif // ifndef SHINY_*_H diff --git a/include/ShinyPrereqs.h b/include/ShinyPrereqs.h index 5056834..7cb00ec 100644 --- a/include/ShinyPrereqs.h +++ b/include/ShinyPrereqs.h @@ -31,17 +31,15 @@ applications, and to alter it and redistribute it freely, subject to the followi #include #endif -namespace Shiny { - //----------------------------------------------------------------------------- -#if SHINY_PROFILER == TRUE - struct ProfileNode; - struct ProfileZone; +#if SHINY_COMPILED == TRUE + struct _ShinyNode; + struct _ShinyZone; - typedef ProfileNode* ProfileNodeCache; - typedef ProfileNode* ProfileNodeTable; + typedef struct _ShinyNode* ProfileNodeCache; + typedef struct _ShinyNode* ProfileNodeTable; #endif @@ -49,7 +47,7 @@ namespace Shiny { #if SHINY_COMPILER == SHINY_COMPILER_MSVC -# define SHINY_INLINE inline +# define SHINY_INLINE __inline # define SHINY_UNUSED #elif SHINY_COMPILER == SHINY_COMPILER_GNUC @@ -79,6 +77,4 @@ namespace Shiny { typedef uint64_t tick_t; -} // namespace Shiny - #endif // ifndef SHINY_*_H diff --git a/include/ShinyTools.h b/include/ShinyTools.h index 8031bce..5504496 100644 --- a/include/ShinyTools.h +++ b/include/ShinyTools.h @@ -26,46 +26,23 @@ applications, and to alter it and redistribute it freely, subject to the followi #include "ShinyPrereqs.h" - -namespace Shiny { - - //----------------------------------------------------------------------------- - struct TimeUnit { - float tickFreq; - float invTickFreq; - const char* suffix; - }; - - const TimeUnit* GetTimeUnit(float ticks); +typedef struct { + float tickFreq; + float invTickFreq; + const char* suffix; +} ShinyTimeUnit; //----------------------------------------------------------------------------- - void GetTicks(tick_t *p); - - const tick_t& GetTickFreq(void); - - float GetTickInvFreq(void); - - -//----------------------------------------------------------------------------- - -#if SHINY_COMPILER == SHINY_COMPILER_MSVC -# pragma warning (push) -# pragma warning(disable: 4311) -#endif - - inline uint32_t ptr32(const void *a_Ptr) { - return reinterpret_cast(a_Ptr); - } +const ShinyTimeUnit* ShinyGetTimeUnit(float ticks); -#if SHINY_COMPILER == SHINY_COMPILER_MSVC -# pragma warning (pop) -#endif +void ShinyGetTicks(tick_t *p); +tick_t ShinyGetTickFreq(void); -} // namespace Shiny +float ShinyGetTickInvFreq(void); #endif // ifndef SHINY_*_H diff --git a/include/ShinyZone.h b/include/ShinyZone.h index a9fc8bc..5e7d0a9 100644 --- a/include/ShinyZone.h +++ b/include/ShinyZone.h @@ -27,66 +27,61 @@ applications, and to alter it and redistribute it freely, subject to the followi #include "ShinyData.h" #include -#if SHINY_PROFILER == TRUE -namespace Shiny { +#if SHINY_COMPILED == TRUE //----------------------------------------------------------------------------- - struct ProfileZone { +#define SHINY_ZONE_STATE_HIDDEN 0 +#define SHINY_ZONE_STATE_INITIALIZED 1 +#define SHINY_ZONE_STATE_UPDATING 2 - enum STATE { - STATE_HIDDEN = 0, - STATE_INITIALIZED, - STATE_UPDATING - }; - //NOTE: data-members are intentionally public because the - // class needs to fulfil the definition of an aggregate - - ProfileZone* next; - - STATE _state; - - mutable const char* name; +//----------------------------------------------------------------------------- - ProfileData data; +typedef struct _ShinyZone { + struct _ShinyZone* next; + int _state; + const char* name; + ShinyData data; +} ShinyZone; - // - bool isInited(void) const { return _state != 0; } +//----------------------------------------------------------------------------- - void init(ProfileZone* a_prev) { - _state = STATE_INITIALIZED; - a_prev->next = this; - } +SHINY_INLINE void ShinyZone_init(ShinyZone *self, ShinyZone* a_prev) { + self->_state = SHINY_ZONE_STATE_INITIALIZED; + a_prev->next = self; +} - void uninit(void) { - _state = STATE_HIDDEN; - next = NULL; - } +SHINY_INLINE void ShinyZone_uninit(ShinyZone *self) { + self->_state = SHINY_ZONE_STATE_HIDDEN; + self->next = NULL; +} - //TODO: se ProfileZone.cpp +void ShinyZone_preUpdateChain(ShinyZone *first); +void ShinyZone_updateChain(ShinyZone *first, float a_damping); +void ShinyZone_updateChainSimple(ShinyZone *first); - void preUpdateChain(void); - void updateChain(float a_damping); - void updateChain(void); +void ShinyZone_resetChain(ShinyZone *first); - void resetChain(void); +ShinyZone* ShinyZone_sortChain(ShinyZone *first); - ProfileZone* sortChain(void); +SHINY_INLINE float ShinyZone_compare(ShinyZone *a, ShinyZone *b) { + return b->data.selfTicks.avg - a->data.selfTicks.avg; +} - bool isUpdating(void) const { return _state == STATE_UPDATING; } +void ShinyZone_enumerateZones(const ShinyZone* a_zone, void (*a_func)(const ShinyZone*)); - void enableUpdating(void) { _state = STATE_UPDATING; } - void disableUpdating(void) { _state = STATE_INITIALIZED; } - - float compare(ProfileZone *zone) { return zone->data.selfTicks.avg - data.selfTicks.avg; } +#if __cplusplus +template +void ShinyZone_enumerateZones(const ShinyZone* a_zone, T* a_this, void (T::*a_func)(const ShinyZone*)) { + (a_this->*a_func)(a_zone); - void clear(void); - }; + if (a_zone->next) ShinyZone_enumerateZones(a_zone->next, a_this, a_func); +} +#endif -} // namespace Shiny -#endif // if SHINY_PROFILER == TRUE +#endif // if SHINY_COMPILED == TRUE #endif // ifndef SHINY_*_H diff --git a/src/ShinyManager.c b/src/ShinyManager.c new file mode 100644 index 0000000..19b144e --- /dev/null +++ b/src/ShinyManager.c @@ -0,0 +1,398 @@ +/* +The zlib/libpng License + +Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net + +This software is provided 'as-is', without any express or implied warranty. In no event will +the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial +applications, and to alter it and redistribute it freely, subject to the following +restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that + you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "ShinyManager.h" + +#include +#include +#include + +#if SHINY_COMPILED == TRUE + + +//----------------------------------------------------------------------------- + +#define TABLE_SIZE_INIT 256 + +//----------------------------------------------------------------------------- + +static ShinyManager Shiny_instance = { +#if SHINY_HAS_ENABLED == TRUE + /* enabled = */ false, +#endif + /* _lastTick = */ 0, + /* _curNode = */ &Shiny_instance.rootNode, + /* _tableMask = */ 0, + /* _nodeTable = */ ShinyManager_dummyNodeTable, +#if SHINY_LOOKUP_RATE == TRUE + /* _lookupCount = */ 0, + /* _lookupSuccessCount = */ 0, +#endif + /* _tableSize = */ 1, + /* nodeCount = */ 1, + /* zoneCount = */ 1, + /* _lastZone = */ &Shiny_instance.rootZone, + /* _lastNodePool = */ NULL, + /* _firstNodePool = */ NULL, + /* rootNode = */ { + /* _last = */ { 0, 0 }, + /* zone = */ &Shiny_instance.rootZone, + /* parent = */ &Shiny_instance.rootNode, + /* nextSibling = */ NULL, + /* firstChild = */ NULL, + /* lastChild = */ NULL, + /* childCount = */ 0, + /* entryLevel = */ 0, + /* _cache = */ NULL, + /* data = */ { { 0, 0 }, { 0, 0 }, { 0, 0 } } + }, + /* rootZone = */ { + /* next = */ NULL, + /* _state = */ SHINY_ZONE_STATE_HIDDEN, + /* name = */ "", + /* data = */ { { 0, 0 }, { 0, 0 }, { 0, 0 } } + }, + /* _initialized = */ FALSE, + /* _firstUpdate = */ TRUE +}; + +static ShinyNode* ShinyManager_dummyNodeTable[] = { NULL }; + + +//----------------------------------------------------------------------------- + +#if SHINY_COMPILER == SHINY_COMPILER_MSVC +# pragma warning (push) +# pragma warning(disable: 4311) +#endif + +// primary hash function +SHINY_INLINE uint32_t hash_value(ShinyNode* a_pParent, ShinyZone* a_pZone) { + uint32_t a = (uint32_t) a_pParent + (uint32_t) a_pZone; + + a = (a+0x7ed55d16) + (a<<12); + a = (a^0xc761c23c) ^ (a>>19); + return a; +} + +// secondary hash used as index offset: force it to be odd +// so it's relatively prime to the power-of-two table size +SHINY_INLINE uint32_t hash_offset(uint32_t a) { + return ((a << 8) + (a >> 4)) | 1; +} + +#if SHINY_COMPILER == SHINY_COMPILER_MSVC +# pragma warning (pop) +#endif + + +//----------------------------------------------------------------------------- + +void ShinyManager_preLoad(ShinyManager *self) { + if (!self->_initialized) { + _ShinyManager_init(self); + + _ShinyManager_createNodeTable(self, TABLE_SIZE_INIT); + _ShinyManager_createNodePool(self, TABLE_SIZE_INIT / 2); + } +} + + +//----------------------------------------------------------------------------- + +void ShinyManager_update(ShinyManager *self, float a_damping) { +#if SHINY_HAS_ENABLED == TRUE + if (!enabled) return; +#endif + + _ShinyManager_appendTicksToCurNode(self); + ShinyZone_preUpdateChain(&self->rootZone); + + if (self->_firstUpdate || a_damping == 0) { + self->_firstUpdate = FALSE; + ShinyNode_updateTreeSimple(&self->rootNode); + ShinyZone_updateChainSimple(&self->rootZone); + + } else { + ShinyNode_updateTree(&self->rootNode, a_damping); + ShinyZone_updateChain(&self->rootZone, a_damping); + } +} + + +//----------------------------------------------------------------------------- + +void ShinyManager_clear(ShinyManager *self) { + ShinyManager_destroy(self); + ShinyManager_preLoad(self); +} + + +//----------------------------------------------------------------------------- + +void ShinyManager_destroy(ShinyManager *self) { + ShinyManager_destroyNodes(self); + ShinyManager_resetZones(self); + _ShinyManager_uninit(self); +} + + +//----------------------------------------------------------------------------- + +ShinyNode* _ShinyManager_lookupNode(ShinyManager *self, ProfileNodeCache* a_cache, ShinyZone* a_zone) { + uint32_t nHash = hash_value(self->_curNode, a_zone); + uint32_t nIndex = nHash & self->_tableMask; + ShinyNode* pNode = self->_nodeTable[nIndex]; + + _ShinyManager_incLookup(self); + _ShinyManager_incLookupSuccess(self); + + if (pNode) { + uint32_t nStep; + + if (ShinyNode_isEqual(pNode, self->_curNode, a_zone)) return pNode; // found it! + + // hash collision: + + // compute a secondary hash function for stepping + nStep = hash_offset(nHash); + + for (;;) { + _ShinyManager_incLookup(self); + + nIndex = (nIndex + nStep) & self->_tableMask; + pNode = self->_nodeTable[nIndex]; + + if (!pNode) break; // found empty slot + else if (ShinyNode_isEqual(pNode, self->_curNode, a_zone)) return pNode; // found it! + } + + // loop is guaranteed to end because the hash table is never full + } + + if (a_zone->_state == SHINY_ZONE_STATE_HIDDEN) { // zone is not initialized + ShinyZone_init(a_zone, self->_lastZone); + + self->_lastZone = a_zone; + self->zoneCount++; + + if (self->_initialized == FALSE) { // first time init + _ShinyManager_init(self); + + _ShinyManager_createNodeTable(self, TABLE_SIZE_INIT); + _ShinyManager_createNodePool(self, TABLE_SIZE_INIT / 2); + + // initialization has invalidated nIndex + // we must compute nIndex again + return _ShinyManager_createNode(self, a_cache, a_zone); + } + } + + // Althouth nodeCount is not updated + // it includes rootNode so it adds up. + + // check if we need to grow the table + // we keep it at most 1/2 full to be very fast + if (self->_tableSize < 2 * self->nodeCount) { + + _ShinyManager_resizeNodeTable(self, 2 * self->_tableSize); + _ShinyManager_resizeNodePool(self, self->nodeCount - 1); + + // resize has invalidated nIndex + // we must compute nIndex again + return _ShinyManager_createNode(self, a_cache, a_zone); + } + + self->nodeCount++; + + { + ShinyNode* pNewNode = ShinyNodePool_newItem(self->_lastNodePool); + ShinyNode_init(pNewNode, self->_curNode, a_zone, a_cache); + + self->_nodeTable[nIndex] = pNewNode; + return pNewNode; + } +} + + +//----------------------------------------------------------------------------- + +ShinyNode* _ShinyManager_createNode(ShinyManager *self, ProfileNodeCache* a_cache, ShinyZone* a_pZone) { + ShinyNode* pNewNode = ShinyNodePool_newItem(self->_lastNodePool); + ShinyNode_init(pNewNode, self->_curNode, a_pZone, a_cache); + + self->nodeCount++; + _ShinyManager_insertNode(pNewNode); + return pNewNode; +} + + +//----------------------------------------------------------------------------- + +void ShinyManager_insertNode(ShinyManager *self, ShinyNode* a_pNode) { + uint32_t nHash = hash_value(a_pNode->parent, a_pNode->zone); + uint32_t nIndex = nHash & self->_tableMask; + + if (self->_nodeTable[nIndex]) { + uint32_t nStep = hash_offset(nHash); + + while (self->_nodeTable[nIndex]) + nIndex = (nIndex + nStep) & self->_tableMask; + } + + self->_nodeTable[nIndex] = a_pNode; +} + + +//----------------------------------------------------------------------------- + +void _ShinyManager_createNodePool(ShinyManager *self, uint32_t a_nCount) { + self->_firstNodePool = ShinyNodePool_create(a_nCount); + self->_lastNodePool = self->_firstNodePool; +} + + +//----------------------------------------------------------------------------- + +void _ShinyManager_resizeNodePool(ShinyManager *self, uint32_t a_nCount) { + ShinyNodePool* pPool = ShinyNodePool_create(a_nCount); + self->_lastNodePool->nextPool = pPool; + self->_lastNodePool = pPool; +} + + +//----------------------------------------------------------------------------- + +void _ShinyManager_createNodeTable(ShinyManager *self, uint32_t a_nCount) { + self->_tableSize = a_nCount; + self->_tableMask = a_nCount - 1; + + self->_nodeTable = (ProfileNodeTable*) + malloc(sizeof(ShinyNode) * a_nCount); + + memset(self->_nodeTable, 0, a_nCount * sizeof(ShinyNode*)); +} + + +//----------------------------------------------------------------------------- + +void _ShinyManager_resizeNodeTable(ShinyManager *self, uint32_t a_nCount) { + ShinyNodePool* pPool; + + free(self->_nodeTable); + _ShinyManager_createNodeTable(self, a_nCount); + + pPool = self->_firstNodePool; + while (pPool) { + + ShinyNode *pIter = ShinyNodePool_firstItem(pPool); + + while (pIter != pPool->_nextItem) + ShinyManager_insertNode(self, pIter++); + + pPool = pPool->nextPool; + } +} + + +//----------------------------------------------------------------------------- + +void ShinyManager_resetZones(ShinyManager *self) { + ShinyZone_resetChain(&self->rootZone); + self->_lastZone = &self->rootZone; + self->zoneCount = 1; +} + + +//----------------------------------------------------------------------------- + +void ShinyManager_destroyNodes(ShinyManager *self) { + if (self->_firstNodePool) { + ShinyNodePool_destroy(self->_firstNodePool); + self->_firstNodePool = NULL; + } + + if (self->_nodeTable != ShinyManager_dummyNodeTable) { + free(self->_nodeTable); + + self->_nodeTable = ShinyManager_dummyNodeTable; + self->_tableSize = 1; + self->_tableMask = 0; + } + + self->_curNode = &self->rootNode; + self->nodeCount = 1; + + _ShinyManager_init(self); +} + + +//----------------------------------------------------------------------------- + +int ShinyManager_outputToFile(ShinyManager *self, const char *a_filename) { + FILE *file = fopen(a_filename, "w"); + + ShinyManager_outputToStream(self, file); + + fclose(file); + return TRUE; +} + + +//----------------------------------------------------------------------------- + +void ShinyManager_outputToStream(ShinyManager *self, FILE *a_stream) { + if (self->_firstUpdate) { + fprintf(a_stream, "!!! Profile data not updated !!!"); + return; + + } else if (!self->_initialized) { + fprintf(a_stream, "!!! No profile was collected !!!"); + return; + + } + +#if SHINY_OUTPUT_MODE & SHINY_OUTPUT_MODE_FLAT + { + int size = ShinyPrintZonesSize(self->zoneCount); + char *buffer = (char*) malloc(size); + ShinyPrintZones(buffer, &self->rootZone); + fwrite(buffer, 1, size - 1, a_stream); + fwrite("\n\n", 1, 2, a_stream); + free(buffer); + } +#endif + +#if SHINY_OUTPUT_MODE & SHINY_OUTPUT_MODE_TREE + { + int size = ShinyPrintNodesSize(self->zoneCount); + char *buffer = (char*) malloc(size); + ShinyPrintNodes(buffer, &self->rootNode); + fwrite(buffer, 1, size - 1, a_stream); + fwrite("\n\n", 1, 2, a_stream); + free(buffer); + } +#endif +} + +#endif // if SHINY_COMPILED == TRUE diff --git a/src/ShinyManager.cpp b/src/ShinyManager.cpp deleted file mode 100644 index 1da20a1..0000000 --- a/src/ShinyManager.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* -The zlib/libpng License - -Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net - -This software is provided 'as-is', without any express or implied warranty. In no event will -the authors be held liable for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, including commercial -applications, and to alter it and redistribute it freely, subject to the following -restrictions: - - 1. The origin of this software must not be misrepresented; you must not claim that - you wrote the original software. If you use this software in a product, - an acknowledgment in the product documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "ShinyManager.h" - -#include -#include -#include - -#if SHINY_PROFILER == TRUE -namespace Shiny { - - -//----------------------------------------------------------------------------- - - ProfileManager ProfileManager::instance = { -#if SHINY_PROFILER_HASENABLED == TRUE - /* enabled = */ false, -#endif - /* _lastTick = */ 0, - /* _curNode = */ &instance.rootNode, - /* _tableMask = */ 0, - /* _nodeTable = */ ProfileManager::_dummyNodeTable, -#if SHINY_PROFILER_LOOKUPRATE == TRUE - /* _lookupCount = */ 0, - /* _lookupSuccessCount = */ 0, -#endif - /* _tableSize = */ 1, - /* nodeCount = */ 1, - /* zoneCount = */ 1, - /* _lastZone = */ &instance.rootZone, - /* _lastNodePool = */ NULL, - /* _firstNodePool = */ NULL, - /* rootNode = */ { - /* _last = */ { 0, 0 }, - /* zone = */ &instance.rootZone, - /* parent = */ &instance.rootNode, - /* nextSibling = */ NULL, - /* firstChild = */ NULL, - /* lastChild = */ NULL, - /* childCount = */ 0, - /* entryLevel = */ 0, - /* _cache = */ NULL, - /* data = */ { { 0, 0 }, { 0, 0 }, { 0, 0 } } - }, - /* rootZone = */ { - /* next = */ NULL, - /* _state = */ ProfileZone::STATE_HIDDEN, - /* name = */ "", - /* data = */ { { 0, 0 }, { 0, 0 }, { 0, 0 } } - }, - /* _initialized = */ false, - /* _firstUpdate = */ true - }; - - ProfileNode* ProfileManager::_dummyNodeTable[] = { NULL }; - - -//----------------------------------------------------------------------------- - - /* Robert Jenkins' 32 bit integer hash function - - SHINY_INLINE uint32_t hash_value(ProfileNode* a_pParent, ProfileZone* a_pZone) { - uint32_t a = ptr32(a_pParent) + ptr32(a_pZone); - - a = (a+0x7ed55d16) + (a<<12); - a = (a^0xc761c23c) ^ (a>>19); - a = (a+0x165667b1) + (a<<5); - a = (a+0xd3a2646c) ^ (a<<9); - a = (a+0xfd7046c5) + (a<<3); - a = (a^0xb55a4f09) ^ (a>>16); - return a; - } - */ - - /* Old hash function - - SHINY_INLINE uint32_t hash_index(ProfileNode* a_pParent, ProfileZone* a_pZone) { - uint32_t a = ptr32(a_pParent) + ptr32(a_pZone); - return (a << 8) - (a >> 4); - } - */ - - // primary hash function - SHINY_INLINE uint32_t hash_value(ProfileNode* a_pParent, ProfileZone* a_pZone) { - uint32_t a = ptr32(a_pParent) + ptr32(a_pZone); - - a = (a+0x7ed55d16) + (a<<12); - a = (a^0xc761c23c) ^ (a>>19); - return a; - } - - // secondary hash used as index offset: force it to be odd - // so it's relatively prime to the power-of-two table size - SHINY_INLINE uint32_t hash_offset(uint32_t a) { - return ((a << 8) + (a >> 4)) | 1; - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::preLoad(void) { - if (!_initialized) { - _init(); - - _createNodeTable(TABLE_SIZE_INIT); - _createNodePool(TABLE_SIZE_INIT / 2); - } - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::update(float a_damping) { -#if SHINY_PROFILER_HASENABLED == TRUE - if (!enabled) return; -#endif - - _appendTicksToCurNode(); - rootZone.preUpdateChain(); - - if (_firstUpdate || a_damping == 0) { - _firstUpdate = false; - rootNode.updateTree(); - rootZone.updateChain(); - - } else { - rootNode.updateTree(a_damping); - rootZone.updateChain(a_damping); - } - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::clear(void) { - destroy(); - preLoad(); - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::destroy(void) { - _destroyNodes(); - _resetZones(); - _uninit(); - } - - -//----------------------------------------------------------------------------- - - ProfileNode* ProfileManager::_lookupNode(ProfileNodeCache* a_cache, ProfileZone* a_zone) { - uint32_t nHash = hash_value(_curNode, a_zone); - uint32_t nIndex = nHash & _tableMask; - ProfileNode* pNode = _nodeTable[nIndex]; - - _incLookup(); - _incLookupSuccess(); - - if (pNode) { - if (pNode->isEqual(_curNode, a_zone)) return pNode; // found it! - - // hash collision: - - // compute a secondary hash function for stepping - uint32_t nStep = hash_offset(nHash); - - for (;;) { - _incLookup(); - - nIndex = (nIndex + nStep) & _tableMask; - pNode = _nodeTable[nIndex]; - - if (!pNode) break; // found empty slot - else if (pNode->isEqual(_curNode, a_zone)) return pNode; // found it! - } - - // loop is guaranteed to end because the hash table is never full - } - - if (!a_zone->isInited()) { // zone is not initialized - a_zone->init(_lastZone); - - _lastZone = a_zone; - zoneCount++; - - if (_initialized == false) { // first time init - _init(); - - _createNodeTable(TABLE_SIZE_INIT); - _createNodePool(TABLE_SIZE_INIT / 2); - - // initialization has invalidated nIndex - // we must compute nIndex again - return _createNode(a_cache, a_zone); - } - } - - // YES nodeCount is not updated - // but it includes rootNode so it adds up. - - // check if we need to grow the table - // we keep it at most 1/2 full to be very fast - if (_tableSize < 2 * nodeCount) { - - _resizeNodeTable(2 * _tableSize); - _resizeNodePool(nodeCount - 1); - - // resize has invalidated nIndex - // we must compute nIndex again - return _createNode(a_cache, a_zone); - } - - nodeCount++; - - ProfileNode* pNewNode = _lastNodePool->newItem(); - pNewNode->init(_curNode, a_zone, a_cache); - - _nodeTable[nIndex] = pNewNode; - return pNewNode; - } - - -//----------------------------------------------------------------------------- - - ProfileNode* ProfileManager::_createNode(ProfileNodeCache* a_cache, ProfileZone* a_pZone) { - ProfileNode* pNewNode = _lastNodePool->newItem(); - pNewNode->init(_curNode, a_pZone, a_cache); - - nodeCount++; - _insertNode(pNewNode); - return pNewNode; - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::_insertNode(ProfileNode* a_pNode) { - uint32_t nHash = hash_value(a_pNode->parent, a_pNode->zone); - uint32_t nIndex = nHash & _tableMask; - - if (_nodeTable[nIndex]) { - uint32_t nStep = hash_offset(nHash); - - while (_nodeTable[nIndex]) - nIndex = (nIndex + nStep) & _tableMask; - } - - _nodeTable[nIndex] = a_pNode; - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::_createNodePool(uint32_t a_nCount) { - _firstNodePool = ProfileNodePool::createNodePool(a_nCount); - _lastNodePool = _firstNodePool; - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::_resizeNodePool(uint32_t a_nCount) { - ProfileNodePool* pPool = ProfileNodePool::createNodePool(a_nCount); - _lastNodePool->nextPool = pPool; - _lastNodePool = pPool; - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::_createNodeTable(uint32_t a_nCount) { - _tableSize = a_nCount; - _tableMask = a_nCount - 1; - - _nodeTable = static_cast( - malloc(sizeof(ProfileNode) * a_nCount)); - - memset(_nodeTable, 0, a_nCount * sizeof(ProfileNode*)); - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::_resizeNodeTable(uint32_t a_nCount) { - ProfileNodePool* pPool; - - free(_nodeTable); - _createNodeTable(a_nCount); - - pPool = _firstNodePool; - while (pPool) { - - ProfileNode *pIter = pPool->firstItem(); - - while (pIter != pPool->unusedItem()) - _insertNode(pIter++); - - pPool = pPool->nextPool; - } - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::_resetZones(void) { - rootZone.resetChain(); - _lastZone = &rootZone; - zoneCount = 1; - } - - -//----------------------------------------------------------------------------- - - void ProfileManager::_destroyNodes(void) { - if (_firstNodePool) { - _firstNodePool->destroy(); - _firstNodePool = NULL; - } - - if (_nodeTable != _dummyNodeTable) { - free(_nodeTable); - - _nodeTable = _dummyNodeTable; - _tableSize = 1; - _tableMask = 0; - } - - _curNode = &rootNode; - nodeCount = 1; - - _init(); - } - - -//----------------------------------------------------------------------------- - - bool ProfileManager::output(const char *a_filename) { - std::ofstream file(a_filename, std::ios_base::out); - - if (!file.is_open()) return false; - else return output(file); - } - - -//----------------------------------------------------------------------------- - - bool ProfileManager::output(std::ostream &a_ostream) { - if (_firstUpdate) { - a_ostream << "!!! Profile data not updated !!!" << std::endl; - return true; - - } else if (!_initialized) { - a_ostream << "!!! No profile started !!!" << std::endl; - return true; - } - - a_ostream << outputZonesAsString().c_str() - << "\n\n" - << outputNodesAsString().c_str() - << "\n\n" - << std::flush; - - return true; - } - - -} // namespace Shiny - -#endif // if SHINY_PROFILER == TRUE diff --git a/src/ShinyNode.c b/src/ShinyNode.c new file mode 100644 index 0000000..7891cc1 --- /dev/null +++ b/src/ShinyNode.c @@ -0,0 +1,129 @@ +/* +The zlib/libpng License + +Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net + +This software is provided 'as-is', without any express or implied warranty. In no event will +the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial +applications, and to alter it and redistribute it freely, subject to the following +restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that + you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "ShinyNode.h" +#include "ShinyZone.h" +#include "ShinyNodeState.h" + +#include + + +#if SHINY_COMPILED == TRUE + +//----------------------------------------------------------------------------- + +static ShinyNode ShinyNode_dummy = { + /* _last = */ { 0, 0 }, + /* zone = */ NULL, + /* parent = */ NULL, + /* nextSibling = */ NULL, + /* firstChild = */ NULL, + /* lastChild = */ NULL +}; + + +//----------------------------------------------------------------------------- + +void ShinyNode_updateTree(ShinyNode* first, float a_damping) { + ShinyNodeState *top = NULL; + ShinyNode *node = first; + + for (;;) { + do { + top = ShinyNodeState_push(top, node); + node = node->firstChild; + } while (node); + + for (;;) { + node = ShinyNodeState_finishAndGetNext(top, a_damping); + top = ShinyNodeState_pop(top); + + if (node) break; + else if (!top) return; + } + } +} + + +//----------------------------------------------------------------------------- + +void ShinyNode_updateTreeSimple(ShinyNode* first) { + ShinyNodeState *top = NULL; + ShinyNode *node = first; + + for (;;) { + do { + top = ShinyNodeState_push(top, node); + node = node->firstChild; + } while (node); + + for (;;) { + node = ShinyNodeState_finishAndGetNextSimple(top); + top = ShinyNodeState_pop(top); + + if (node) break; + else if (!top) return; + } + } +} + + +//----------------------------------------------------------------------------- + +const ShinyNode* ShinyNode_findNextInTree(const ShinyNode* self) { + if (self->firstChild) { + return self->firstChild; + + } else if (self->nextSibling) { + return self->nextSibling; + + } else { + ShinyNode* pParent = self->parent; + + while (!ShinyNode_isRoot(pParent)) { + if (pParent->nextSibling) return pParent->nextSibling; + else pParent = pParent->parent; + } + + return NULL; + } +} + + +//----------------------------------------------------------------------------- + +void ShinyNode_clear(ShinyNode* self) { + memset(self, 0, sizeof(ShinyNode)); +} + + +//----------------------------------------------------------------------------- + +void ShinyNode_enumerateNodes(const ShinyNode* a_node, void (*a_func)(const ShinyNode*)) { + a_func(a_node); + + if (a_node->firstChild) ShinyNode_enumerateNodes(a_node->firstChild, a_func); + if (a_node->nextSibling) ShinyNode_enumerateNodes(a_node->nextSibling, a_func); +} + +#endif diff --git a/src/ShinyNode.cpp b/src/ShinyNode.cpp deleted file mode 100644 index 30069ff..0000000 --- a/src/ShinyNode.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* -The zlib/libpng License - -Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net - -This software is provided 'as-is', without any express or implied warranty. In no event will -the authors be held liable for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, including commercial -applications, and to alter it and redistribute it freely, subject to the following -restrictions: - - 1. The origin of this software must not be misrepresented; you must not claim that - you wrote the original software. If you use this software in a product, - an acknowledgment in the product documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "ShinyNode.h" -#include "ShinyZone.h" - -#include -#include - - -#if SHINY_PROFILER == TRUE -namespace Shiny { - -//----------------------------------------------------------------------------- - - ProfileNode ProfileNode::_dummy = { - /* _last = */ { 0, 0 }, - /* zone = */ NULL, - /* parent = */ NULL, - /* nextSibling = */ NULL, - /* firstChild = */ NULL, - /* lastChild = */ NULL - }; - - -//----------------------------------------------------------------------------- - - struct ProfileNodeState { - ProfileNode *node; - bool zoneUpdating; - - ProfileNodeState(ProfileNode *a_node); - ProfileNode* finishAndGetNext(float a_damping); - ProfileNode* finishAndGetNext(void); - }; - - -//----------------------------------------------------------------------------- - - ProfileNodeState::ProfileNodeState(ProfileNode *a_node) : node(a_node) { - ProfileZone *zone = node->zone; - ProfileData &data = node->data; - ProfileLastData &_last = node->_last; - - data.selfTicks.cur = _last.selfTicks; - data.entryCount.cur = _last.entryCount; - - zone->data.selfTicks.cur += _last.selfTicks; - zone->data.entryCount.cur += _last.entryCount; - - data.childTicks.cur = 0; - _last.selfTicks = 0; - _last.entryCount = 0; - - zoneUpdating = !zone->isUpdating(); - if (zoneUpdating) { - zone->enableUpdating(); - } else { - zone->data.childTicks.cur -= data.selfTicks.cur; - } - } - - -//----------------------------------------------------------------------------- - - ProfileNode* ProfileNodeState::finishAndGetNext(float a_damping) { - ProfileZone *zone = node->zone; - ProfileData &data = node->data; - - if (zoneUpdating) { - zone->data.childTicks.cur += data.childTicks.cur; - zone->disableUpdating(); - } - - data.computeAverage(a_damping); - - if (!node->isRoot()) - node->parent->data.childTicks.cur += data.selfTicks.cur + data.childTicks.cur; - - return node->nextSibling; - } - - -//----------------------------------------------------------------------------- - - ProfileNode* ProfileNodeState::finishAndGetNext(void) { - ProfileZone *zone = node->zone; - ProfileData &data = node->data; - - if (zoneUpdating) { - zone->data.childTicks.cur += data.childTicks.cur; - zone->disableUpdating(); - } - - data.copyAverage(); - - if (!node->isRoot()) - node->parent->data.childTicks.cur += data.selfTicks.cur + data.childTicks.cur; - - return node->nextSibling; - } - - -//----------------------------------------------------------------------------- - - void ProfileNode::updateTree(float a_damping) { - std::stack up; - ProfileNode *node = this; - - for (;;) { - do { - up.push(ProfileNodeState(node)); - node = node->firstChild; - } while (node); - - for (;;) { - node = up.top().finishAndGetNext(a_damping); - up.pop(); - - if (node) break; - else if (up.empty()) return; - } - } - } - - -//----------------------------------------------------------------------------- - - void ProfileNode::updateTree(void) { - std::stack up; - ProfileNode *node = this; - - for (;;) { - do { - up.push(ProfileNodeState(node)); - node = node->firstChild; - } while (node); - - for (;;) { - node = up.top().finishAndGetNext(); - up.pop(); - - if (node) break; - else if (up.empty()) return; - } - } - } - - -//----------------------------------------------------------------------------- - - const ProfileNode* ProfileNode::findNextInTree(void) const { - if (firstChild) { - return firstChild; - - } else if (nextSibling) { - return nextSibling; - - } else { - ProfileNode* pParent = parent; - - while (!pParent->isRoot()) { - if (pParent->nextSibling) return pParent->nextSibling; - else pParent = pParent->parent; - } - - return NULL; - } - } - - -//----------------------------------------------------------------------------- - - void ProfileNode::clear(void) { - memset(this, 0, sizeof(ProfileNode)); - } - - -} // namespace Shiny -#endif diff --git a/src/ShinyNodePool.cpp b/src/ShinyNodePool.c similarity index 54% rename from src/ShinyNodePool.cpp rename to src/ShinyNodePool.c index 991d0f5..5a0e5a3 100644 --- a/src/ShinyNodePool.cpp +++ b/src/ShinyNodePool.c @@ -27,49 +27,51 @@ applications, and to alter it and redistribute it freely, subject to the followi #include #include -#if SHINY_PROFILER == TRUE -namespace Shiny { +#if SHINY_COMPILED == TRUE //----------------------------------------------------------------------------- - ProfileNodePool* ProfileNodePool::createNodePool(uint32_t a_items) { - ProfileNodePool* pPool = static_cast( - malloc(sizeof(ProfileNodePool) + sizeof(T) * (a_items - 1))); +ShinyNodePool* ShinyNodePool_create(uint32_t a_items) { + ShinyNodePool* pPool = (ShinyNodePool*) + malloc(sizeof(ShinyNodePool) + sizeof(ShinyNode) * (a_items - 1)); - pPool->nextPool = NULL; - pPool->_nextItem = &pPool->_items[0]; - pPool->endOfItems = &pPool->_items[a_items]; + pPool->nextPool = NULL; + pPool->_nextItem = &pPool->_items[0]; + pPool->endOfItems = &pPool->_items[a_items]; - memset(&pPool->_items[0], 0, a_items * sizeof(T)); - return pPool; - } + memset(&pPool->_items[0], 0, a_items * sizeof(ShinyNode)); + return pPool; +} //----------------------------------------------------------------------------- - uint32_t ProfileNodePool::memoryUsageChain(void) { - uint32_t bytes = ptr32( - reinterpret_cast( - reinterpret_cast(endOfItems) - - reinterpret_cast(this))); +uint32_t ShinyNodePool_memoryUsageChain(ShinyNodePool *first) { + uint32_t bytes = (uint32_t) ((char*) first->endOfItems - (char*) first); + ShinyNodePool *pool = first->nextPool; - if (nextPool) bytes += nextPool->memoryUsageChain(); - return bytes; + while (pool) { + bytes += (uint32_t) ((char*) pool->endOfItems - (char*) pool); + pool = pool->nextPool; } + return bytes; +} + //----------------------------------------------------------------------------- - void ProfileNodePool::destroy(void) { - T* pItem = firstItem(); +void ShinyNodePool_destroy(ShinyNodePool *self) { + ShinyNode* firstNode = ShinyNodePool_firstItem(self); + ShinyNode* lastNode = self->_nextItem; - while (pItem != unusedItem()) - (pItem++)->destroy(); + while (firstNode != lastNode) + ShinyNode_destroy(firstNode++); - if (nextPool) nextPool->destroy(); - free(this); - } + // TODO: make this into a loop or a tail recursion + if (self->nextPool) ShinyNodePool_destroy(self->nextPool); + free(self); +} -} // namespace Shiny #endif diff --git a/src/ShinyOutput.c b/src/ShinyOutput.c new file mode 100644 index 0000000..b6c557b --- /dev/null +++ b/src/ShinyOutput.c @@ -0,0 +1,152 @@ +/* +The zlib/libpng License + +Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net + +This software is provided 'as-is', without any express or implied warranty. In no event will +the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial +applications, and to alter it and redistribute it freely, subject to the following +restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that + you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "ShinyOutput.h" + +#include + +#if SHINY_COMPILER == SHINY_COMPILER_MSVC +# pragma warning(disable: 4996) +# define snprintf _snprintf +# define TRAILING 0 + +#else +# define TRAILING 1 +#endif + +#if SHINY_COMPILED == TRUE + + +//----------------------------------------------------------------------------- + +#define OUTPUT_WIDTH_CALL 6 +#define OUTPUT_WIDTH_TIME 6 +#define OUTPUT_WIDTH_PERC 4 +#define OUTPUT_WIDTH_SUM 79 + +#define OUTPUT_WIDTH_DATA (1+OUTPUT_WIDTH_CALL + 1 + 2*(OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1) + 1) +#define OUTPUT_WIDTH_NAME (OUTPUT_WIDTH_SUM - OUTPUT_WIDTH_DATA) + + +//----------------------------------------------------------------------------- + +void _printHeader(char *dest, const char *a_title) { + snprintf(dest, OUTPUT_WIDTH_SUM + TRAILING, + "%-*s %*s %*s %*s", + OUTPUT_WIDTH_NAME, a_title, + OUTPUT_WIDTH_CALL, "calls", + OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1, "self time", + OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1, "total time"); +} + + +//----------------------------------------------------------------------------- + +void _printData(char *dest, const ShinyData *a_data, float a_topercent) { + float totalTicksAvg = ShinyData_totalTicksAvg(a_data); + const ShinyTimeUnit *selfUnit = ShinyGetTimeUnit(a_data->selfTicks.avg); + const ShinyTimeUnit *totalUnit = ShinyGetTimeUnit(totalTicksAvg); + + snprintf(dest, OUTPUT_WIDTH_DATA + TRAILING, + " %*.1f %*.0f %-2s %*.0f%% %*.0f %-2s %*.0f%%", + OUTPUT_WIDTH_CALL, a_data->entryCount.avg, + OUTPUT_WIDTH_TIME, a_data->selfTicks.avg * selfUnit->invTickFreq, selfUnit->suffix, + OUTPUT_WIDTH_PERC, a_data->selfTicks.avg * a_topercent, + OUTPUT_WIDTH_TIME, totalTicksAvg * totalUnit->invTickFreq, totalUnit->suffix, + OUTPUT_WIDTH_PERC, totalTicksAvg * a_topercent); +} + + +//----------------------------------------------------------------------------- + +int ShinyPrintNodesSize(uint32_t a_count) { + return (1 + a_count) * (OUTPUT_WIDTH_SUM + 1); +} + + +//----------------------------------------------------------------------------- + +int ShinyPrintZonesSize(uint32_t a_count) { + return (1 + a_count) * (OUTPUT_WIDTH_SUM + 1); +} + + +//----------------------------------------------------------------------------- + +void ShinyPrintNodesToString(char* output, const ShinyNode *a_root) { + float fTicksToPc = 100.0f / a_root->data.childTicks.avg; + const ShinyNode *node = a_root; + char *s = output; + + _printHeader(s, "call tree"); + s += OUTPUT_WIDTH_SUM; + (*s++) = '\n'; + + do { + int offset = node->entryLevel * 2; + snprintf(s, OUTPUT_WIDTH_NAME + TRAILING, "%*s%-*s", + offset, "", OUTPUT_WIDTH_NAME - offset, node->zone->name); + + s += OUTPUT_WIDTH_NAME; + + _printData(s, &(node->data), fTicksToPc); + + s += OUTPUT_WIDTH_DATA; + (*s++) = '\n'; + + node = ShinyNode_findNextInTree(node); + } while (node); + + *(--s) = '\0'; +} + + +//----------------------------------------------------------------------------- + +void ShinyPrintZonesToString(char* output, const ShinyZone *a_root) { + float fTicksToPc = 100.0f / a_root->data.childTicks.avg; + const ShinyZone *zone = a_root; + char *s = output; + + _printHeader(s, "flat profile"); + s += OUTPUT_WIDTH_SUM; + (*s++) = '\n'; + + do { + snprintf(s, OUTPUT_WIDTH_NAME + TRAILING, "%-*s", + OUTPUT_WIDTH_NAME, zone->name); + + s += OUTPUT_WIDTH_NAME; + + _printData(s, &(zone->data), fTicksToPc); + + s += OUTPUT_WIDTH_DATA; + (*s++) = '\n'; + + zone = zone->next; + } while (zone); + + *(--s) = '\0'; +} + +#endif diff --git a/src/ShinyOutput.cpp b/src/ShinyOutput.cpp deleted file mode 100644 index e4e3044..0000000 --- a/src/ShinyOutput.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* -The zlib/libpng License - -Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net - -This software is provided 'as-is', without any express or implied warranty. In no event will -the authors be held liable for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, including commercial -applications, and to alter it and redistribute it freely, subject to the following -restrictions: - - 1. The origin of this software must not be misrepresented; you must not claim that - you wrote the original software. If you use this software in a product, - an acknowledgment in the product documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "ShinyOutput.h" - -#include - -#if SHINY_COMPILER == SHINY_COMPILER_MSVC -# pragma warning(disable: 4996) -# define snprintf _snprintf -# define TRAILING 0 - -#else -# define TRAILING 1 -#endif - -#if SHINY_PROFILER == TRUE -namespace Shiny { - - -//----------------------------------------------------------------------------- - - void _printHeader(char *dest, const char *a_title) { - snprintf(dest, OUTPUT_WIDTH_SUM + TRAILING, - "%-*s %*s %*s %*s", - OUTPUT_WIDTH_NAME, a_title, - OUTPUT_WIDTH_CALL, "calls", - OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1, "self time", - OUTPUT_WIDTH_TIME+4+OUTPUT_WIDTH_PERC+1, "total time"); - } - - -//----------------------------------------------------------------------------- - - void _printData(char *dest, const ProfileData &a_data, float a_topercent) { - float totalTicksAvg = a_data.totalTicksAvg(); - const TimeUnit *selfUnit = GetTimeUnit(a_data.selfTicks.avg); - const TimeUnit *totalUnit = GetTimeUnit(totalTicksAvg); - - snprintf(dest, OUTPUT_WIDTH_DATA + TRAILING, - " %*.1f %*.0f %-2s %*.0f%% %*.0f %-2s %*.0f%%", - OUTPUT_WIDTH_CALL, a_data.entryCount.avg, - OUTPUT_WIDTH_TIME, a_data.selfTicks.avg * selfUnit->invTickFreq, selfUnit->suffix, - OUTPUT_WIDTH_PERC, a_data.selfTicks.avg * a_topercent, - OUTPUT_WIDTH_TIME, totalTicksAvg * totalUnit->invTickFreq, totalUnit->suffix, - OUTPUT_WIDTH_PERC, totalTicksAvg * a_topercent); - } - -//----------------------------------------------------------------------------- - - std::string OutputNodesAsString(const ProfileNode *a_root, uint32_t a_count) { - float fTicksToPc = 100.0f / a_root->data.childTicks.avg; - std::string str; - - str.resize((1 + a_count) * (OUTPUT_WIDTH_SUM + 1) - 1); - char *s = &str[0]; - - _printHeader(s, "call tree"); - s += OUTPUT_WIDTH_SUM; - (*s++) = '\n'; - - const ProfileNode *node = a_root; - - do { - int offset = node->entryLevel * 2; - snprintf(s, OUTPUT_WIDTH_NAME + TRAILING, "%*s%-*s", - offset, "", OUTPUT_WIDTH_NAME - offset, node->zone->name); - - s += OUTPUT_WIDTH_NAME; - - _printData(s, node->data, fTicksToPc); - - s += OUTPUT_WIDTH_DATA; - (*s++) = '\n'; - - node = node->findNextInTree(); - } while (node); - - *(--s) = '\0'; - return str; - } - - -//----------------------------------------------------------------------------- - - std::string OutputZonesAsString(const ProfileZone *a_root, uint32_t a_count) { - float fTicksToPc = 100.0f / a_root->data.childTicks.avg; - std::string str; - - str.resize((1 + a_count) * (OUTPUT_WIDTH_SUM + 1) - 1); - char *s = &str[0]; - - _printHeader(s, "flat profile"); - s += OUTPUT_WIDTH_SUM; - (*s++) = '\n'; - - const ProfileZone *zone = a_root; - - do { - snprintf(s, OUTPUT_WIDTH_NAME + TRAILING, "%-*s", - OUTPUT_WIDTH_NAME, zone->name); - - s += OUTPUT_WIDTH_NAME; - - _printData(s, zone->data, fTicksToPc); - - s += OUTPUT_WIDTH_DATA; - (*s++) = '\n'; - - zone = zone->next; - } while (zone); - - *(--s) = '\0'; - return str; - } - -} // namespace Shiny -#endif diff --git a/src/ShinyTools.c b/src/ShinyTools.c new file mode 100644 index 0000000..76472f5 --- /dev/null +++ b/src/ShinyTools.c @@ -0,0 +1,105 @@ +/* +The zlib/libpng License + +Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net + +This software is provided 'as-is', without any express or implied warranty. In no event will +the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial +applications, and to alter it and redistribute it freely, subject to the following +restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that + you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "ShinyTools.h" + +#if SHINY_PLATFORM == SHINY_PLATFORM_WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +#elif SHINY_PLATFORM == SHINY_PLATFORM_POSIX +#include +#endif + + +//----------------------------------------------------------------------------- + +const ShinyTimeUnit* ShinyGetTimeUnit(float ticks) { + static ShinyTimeUnit units[4] = { 0 }; + + if (units[0].tickFreq == 0) { // auto initialize first time + units[0].tickFreq = ShinyGetTickFreq() / 1.0f; + units[0].invTickFreq = ShinyGetTickInvFreq() * 1.0f; + units[0].suffix = "s"; + + units[1].tickFreq = ShinyGetTickFreq() / 1000.0f; + units[1].invTickFreq = ShinyGetTickInvFreq() * 1000.0f; + units[1].suffix = "ms"; + + units[2].tickFreq = ShinyGetTickFreq() / 1000000.0f; + units[2].invTickFreq = ShinyGetTickInvFreq() * 1000000.0f; + units[2].suffix = "us"; + + units[3].tickFreq = ShinyGetTickFreq() / 1000000000.0f; + units[3].invTickFreq = ShinyGetTickInvFreq() * 1000000000.0f; + units[3].suffix = "ns"; + } + + if (units[0].tickFreq < ticks) return &units[0]; + else if (units[1].tickFreq < ticks) return &units[1]; + else if (units[2].tickFreq < ticks) return &units[2]; + else return &units[3]; +} + + +//----------------------------------------------------------------------------- + +#if SHINY_PLATFORM == SHINY_PLATFORM_WIN32 + +void ShinyGetTicks(tick_t *p) { + QueryPerformanceCounter((LARGE_INTEGER*)(p)); +} + +tick_t ShinyGetTickFreq(void) { + static tick_t freq = 0; + if (freq == 0) QueryPerformanceFrequency((LARGE_INTEGER*)(&freq)); + return freq; +} + +float ShinyGetTickInvFreq(void) { + static float invfreq = 0; + if (invfreq == 0) invfreq = 1.0f / ShinyGetTickFreq(); + return invfreq; +} + + +//----------------------------------------------------------------------------- + +#elif SHINY_PLATFORM == SHINY_PLATFORM_POSIX + +void ShinyGetTicks(tick_t *p) { + timeval time; + gettimeofday(&time, NULL); + + *p = time.tv_sec * 1000000 + time.tv_usec; +} + +const tick_t& ShinyGetTickFreq(void) { + return 1000000; +} + +float ShinyGetTickInvFreq(void) { + return 1.0f / 1000000.0f; +} + +#endif diff --git a/src/ShinyTools.cpp b/src/ShinyTools.cpp deleted file mode 100644 index 3ce5534..0000000 --- a/src/ShinyTools.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* -The zlib/libpng License - -Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net - -This software is provided 'as-is', without any express or implied warranty. In no event will -the authors be held liable for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, including commercial -applications, and to alter it and redistribute it freely, subject to the following -restrictions: - - 1. The origin of this software must not be misrepresented; you must not claim that - you wrote the original software. If you use this software in a product, - an acknowledgment in the product documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "ShinyTools.h" - -#if SHINY_PLATFORM == SHINY_PLATFORM_WIN32 -#define WIN32_LEAN_AND_MEAN -#include - -#elif SHINY_PLATFORM == SHINY_PLATFORM_POSIX -#include -#endif - -namespace Shiny { - - -//----------------------------------------------------------------------------- - - const TimeUnit* GetTimeUnit(float ticks) { - static TimeUnit unit[] = { - { GetTickFreq() / 1.0f , GetTickInvFreq() * 1.0f , "s" }, - { GetTickFreq() / 1000.0f , GetTickInvFreq() * 1000.0f , "ms" }, - { GetTickFreq() / 1000000.0f , GetTickInvFreq() * 1000000.0f , "us" }, - { GetTickFreq() / 1000000000.0f , GetTickInvFreq() * 1000000000.0f , "ns" } - }; - - if (unit[0].tickFreq < ticks) return &unit[0]; - else if (unit[1].tickFreq < ticks) return &unit[1]; - else if (unit[2].tickFreq < ticks) return &unit[2]; - else return &unit[3]; - } - - -//----------------------------------------------------------------------------- - -#if SHINY_PLATFORM == SHINY_PLATFORM_WIN32 - - tick_t _InitTickFreq(void) { - tick_t freq; - - QueryPerformanceFrequency(reinterpret_cast(&freq)); - return freq; - } - - void GetTicks(tick_t *p) { - QueryPerformanceCounter(reinterpret_cast(p)); - } - - const tick_t& GetTickFreq(void) { - static tick_t freq = _InitTickFreq(); - return freq; - } - - float GetTickInvFreq(void) { - static float invfreq = 1.0f / GetTickFreq(); - return invfreq; - } - - -//----------------------------------------------------------------------------- - -#elif SHINY_PLATFORM == SHINY_PLATFORM_POSIX - - void GetTicks(tick_t *p) { - timeval time; - gettimeofday(&time, NULL); - - *p = time.tv_sec * 1000000 + time.tv_usec; - } - - const tick_t& GetTickFreq(void) { - return 1000000; - } - - float GetTickInvFreq(void) { - return 1.0f / 1000000.0f; - } - -#endif -} // namespace Shiny diff --git a/src/ShinyZone.c b/src/ShinyZone.c new file mode 100644 index 0000000..28bd0af --- /dev/null +++ b/src/ShinyZone.c @@ -0,0 +1,171 @@ +/* +The zlib/libpng License + +Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net + +This software is provided 'as-is', without any express or implied warranty. In no event will +the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial +applications, and to alter it and redistribute it freely, subject to the following +restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that + you wrote the original software. If you use this software in a product, + an acknowledgment in the product documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "ShinyZone.h" + +#if SHINY_COMPILED == TRUE + +//----------------------------------------------------------------------------- + +//TODO: these loops loop for ever - find out why. + +void ShinyZone_preUpdateChain(ShinyZone *first) { + ShinyZone* zone = first; + + while (zone) { + ShinyData_clearCurrent(&(zone->data)); + zone = zone->next; + } +} + + +//----------------------------------------------------------------------------- + +void ShinyZone_updateChain(ShinyZone *first, float a_damping) { + ShinyZone* zone = first; + + do { + ShinyData_computeAverage(&(zone->data), a_damping); + zone = zone->next; + } while (zone); +} + + +//----------------------------------------------------------------------------- + +void ShinyZone_updateChainSimple(ShinyZone *first) { + ShinyZone* zone = first; + + do { + ShinyData_copyAverage(&(zone->data)); + zone = zone->next; + } while (zone); +} + + +//----------------------------------------------------------------------------- + +void ShinyZone_resetChain(ShinyZone *first) { + ShinyZone* zone = first, *temp; + + do { + zone->_state = SHINY_ZONE_STATE_HIDDEN; + temp = zone->next; + zone->next = NULL; + zone = temp; + } while (zone); +} + +//----------------------------------------------------------------------------- + +/* + * This is the actual sort function. Notice that it returns the new + * head of the list. (It has to, because the head will not + * generally be the same ShinyZone after the sort.) So unlike sorting + * an array, where you can do + * + * sort(myarray); + * + * you now have to do + * + * list = listsort(mylist); + */ +ShinyZone* ShinyZone_sortChain(ShinyZone *first) { + ShinyZone *p, *q, *e, *tail, *list = first; + int insize, nmerges, psize, qsize, i; + + insize = 1; + + while (1) { + p = list; + list = NULL; + tail = NULL; + + nmerges = 0; /* count number of merges we do in this pass */ + + while (p) { + nmerges++; /* there exists a merge to be done */ + /* step `insize' places along from p */ + q = p; + psize = 0; + for (i = 0; i < insize; i++) { + psize++; + q = q->next; + if (!q) break; + } + + /* if q hasn't fallen off end, we have two lists to merge */ + qsize = insize; + + /* now we have two lists; merge them */ + while (psize > 0 || (qsize > 0 && q)) { + + /* decide whether next ShinyZone of merge comes from p or q */ + if (psize == 0) { + /* p is empty; e must come from q. */ + e = q; q = q->next; qsize--; + } else if (qsize == 0 || !q) { + /* q is empty; e must come from p. */ + e = p; p = p->next; psize--; + } else if (ShinyZone_compare(p, q) <= 0) { + /* First ShinyZone of p is lower (or same); + * e must come from p. */ + e = p; p = p->next; psize--; + } else { + /* First ShinyZone of q is lower; e must come from q. */ + e = q; q = q->next; qsize--; + } + + /* add the next ShinyZone to the merged list */ + if (tail) { + tail->next = e; + } else { + list = e; + } + tail = e; + } + + /* now p has stepped `insize' places along, and q has too */ + p = q; + } + + tail->next = NULL; + + /* If we have done only one merge, we're finished. */ + if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ + return list; + + /* Otherwise repeat, merging lists twice the size */ + insize *= 2; + } +} + +//----------------------------------------------------------------------------- + +void ShinyZone_enumerateZones(const ShinyZone* a_zone, void (*a_func)(const ShinyZone*)) { + a_func(a_zone); + + if (a_zone->next) ShinyZone_enumerateZones(a_zone->next, a_func); +} + +#endif diff --git a/src/ShinyZone.cpp b/src/ShinyZone.cpp deleted file mode 100644 index cdcf2db..0000000 --- a/src/ShinyZone.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* -The zlib/libpng License - -Copyright (c) 2007 Aidin Abedi, http://shinyprofiler.sourceforge.net - -This software is provided 'as-is', without any express or implied warranty. In no event will -the authors be held liable for any damages arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, including commercial -applications, and to alter it and redistribute it freely, subject to the following -restrictions: - - 1. The origin of this software must not be misrepresented; you must not claim that - you wrote the original software. If you use this software in a product, - an acknowledgment in the product documentation would be appreciated but is - not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "ShinyZone.h" - -#include - -#if SHINY_PROFILER == TRUE -namespace Shiny { - -//----------------------------------------------------------------------------- - - //TODO: these loops loop for ever - find out why. - - void ProfileZone::preUpdateChain(void) { - ProfileZone* zone = this; - - while (zone) { - zone->data.clearCurrent(); - zone = zone->next; - } - } - - -//----------------------------------------------------------------------------- - - void ProfileZone::updateChain(float a_damping) { - ProfileZone* zone = this; - - do { - zone->data.computeAverage(a_damping); - zone = zone->next; - } while (zone); - } - - -//----------------------------------------------------------------------------- - - void ProfileZone::updateChain(void) { - ProfileZone* zone = this; - - do { - zone->data.copyAverage(); - zone = zone->next; - } while (zone); - } - - -//----------------------------------------------------------------------------- - - void ProfileZone::resetChain(void) { - ProfileZone* zone = this, *temp; - - do { - zone->_state = STATE_HIDDEN; - temp = zone->next; - zone->next = NULL; - zone = temp; - } while (zone); - } - -//----------------------------------------------------------------------------- - - void ProfileZone::clear(void) { - memset(this, 0, sizeof(ProfileZone)); - } - -//----------------------------------------------------------------------------- - - /* - * This is the actual sort function. Notice that it returns the new - * head of the list. (It has to, because the head will not - * generally be the same ProfileZone after the sort.) So unlike sorting - * an array, where you can do - * - * sort(myarray); - * - * you now have to do - * - * list = listsort(mylist); - */ - ProfileZone* ProfileZone::sortChain(void) { - ProfileZone *p, *q, *e, *tail, *list = this; - int insize, nmerges, psize, qsize, i; - - insize = 1; - - while (1) { - p = list; - list = NULL; - tail = NULL; - - nmerges = 0; /* count number of merges we do in this pass */ - - while (p) { - nmerges++; /* there exists a merge to be done */ - /* step `insize' places along from p */ - q = p; - psize = 0; - for (i = 0; i < insize; i++) { - psize++; - q = q->next; - if (!q) break; - } - - /* if q hasn't fallen off end, we have two lists to merge */ - qsize = insize; - - /* now we have two lists; merge them */ - while (psize > 0 || (qsize > 0 && q)) { - - /* decide whether next ProfileZone of merge comes from p or q */ - if (psize == 0) { - /* p is empty; e must come from q. */ - e = q; q = q->next; qsize--; - } else if (qsize == 0 || !q) { - /* q is empty; e must come from p. */ - e = p; p = p->next; psize--; - } else if (p->compare(q) <= 0) { - /* First ProfileZone of p is lower (or same); - * e must come from p. */ - e = p; p = p->next; psize--; - } else { - /* First ProfileZone of q is lower; e must come from q. */ - e = q; q = q->next; qsize--; - } - - /* add the next ProfileZone to the merged list */ - if (tail) { - tail->next = e; - } else { - list = e; - } - tail = e; - } - - /* now p has stepped `insize' places along, and q has too */ - p = q; - } - - tail->next = NULL; - - /* If we have done only one merge, we're finished. */ - if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ - return list; - - /* Otherwise repeat, merging lists twice the size */ - insize *= 2; - } - } - - -} // namespace Shiny -#endif diff --git a/src/Shiny_vs2003.vcproj b/src/Shiny_vs2003.vcproj deleted file mode 100644 index 51117f2..0000000 --- a/src/Shiny_vs2003.vcproj +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Shiny_vs2005.vcproj b/src/Shiny_vs2005.vcproj deleted file mode 100644 index a990267..0000000 --- a/src/Shiny_vs2005.vcproj +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Shiny_vs2008.vcproj b/src/Shiny_vs2008.vcproj index 852ceb3..27ee708 100644 --- a/src/Shiny_vs2008.vcproj +++ b/src/Shiny_vs2008.vcproj @@ -151,27 +151,31 @@ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + @@ -212,6 +216,10 @@ RelativePath="..\include\ShinyNodePool.h" > + +