Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/Shiny/ShinyManager.c')
-rw-r--r--src/Shiny/ShinyManager.c445
1 files changed, 445 insertions, 0 deletions
diff --git a/src/Shiny/ShinyManager.c b/src/Shiny/ShinyManager.c
new file mode 100644
index 000000000..6b2811851
--- /dev/null
+++ b/src/Shiny/ShinyManager.c
@@ -0,0 +1,445 @@
+/*
+The MIT License
+
+Copyright (c) 2007-2010 Aidin Abedi http://code.google.com/p/shinyprofiler/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifdef SLIC3R_PROFILE
+
+#include "ShinyManager.h"
+
+#include <malloc.h>
+#include <memory.h>
+#include <string.h>
+#include <stdio.h>
+
+/*---------------------------------------------------------------------------*/
+
+#define TABLE_SIZE_INIT 256
+
+/*---------------------------------------------------------------------------*/
+
+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 = */ "<unprofiled>",
+ /* data = */ { { 0, 0 }, { 0, 0 }, { 0, 0 } }
+ },
+ /* damping = */ 0.f, // Damping disabled, every PROFILE_UPDATE will be performed from scratch. Original value: 0.9f
+ /* _initialized = */ FALSE,
+ /* _firstUpdate = */ TRUE
+};
+
+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(void* a_pParent, void* a_pZone) {
+ uint32_t a = (uint32_t) a_pParent + (uint32_t) a_pZone;
+// uint32_t a = *reinterpret_cast<uint32_t*>(&a_pParent) + *reinterpret_cast<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) {
+#if SHINY_HAS_ENABLED == TRUE
+ if (!enabled) return;
+#endif
+
+ _ShinyManager_appendTicksToCurNode(self);
+ ShinyZone_preUpdateChain(&self->rootZone);
+
+ if (self->_firstUpdate || self->damping == 0) {
+ self->_firstUpdate = FALSE;
+ ShinyNode_updateTreeClean(&self->rootNode);
+ ShinyZone_updateChainClean(&self->rootZone);
+
+ } else {
+ ShinyNode_updateTree(&self->rootNode, self->damping);
+ ShinyZone_updateChain(&self->rootZone, self->damping);
+ }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+void ShinyManager_updateClean(ShinyManager *self) {
+#if SHINY_HAS_ENABLED == TRUE
+ if (!enabled) return;
+#endif
+
+ _ShinyManager_appendTicksToCurNode(self);
+ ShinyZone_preUpdateChain(&self->rootZone);
+
+ self->_firstUpdate = FALSE;
+ ShinyNode_updateTreeClean(&self->rootNode);
+ ShinyZone_updateChainClean(&self->rootZone);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+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, ShinyNodeCache *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;
+ }
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+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;
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+ShinyNode* _ShinyManager_createNode(ShinyManager *self, ShinyNodeCache* a_cache, ShinyZone* a_pZone) {
+ ShinyNode* pNewNode = ShinyNodePool_newItem(self->_lastNodePool);
+ ShinyNode_init(pNewNode, self->_curNode, a_pZone, a_cache);
+
+ self->nodeCount++;
+ _ShinyManager_insertNode(self, pNewNode);
+ return pNewNode;
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+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 = (ShinyNodeTable*)
+ 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);
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+const char* ShinyManager_getOutputErrorString(ShinyManager *self) {
+ if (self->_firstUpdate) return "!!! Profile data must first be updated !!!";
+ else if (!self->_initialized) return "!!! No profiles where executed !!!";
+ else return NULL;
+}
+
+
+/*---------------------------------------------------------------------------*/
+
+#if SHINY_COMPILER == SHINY_COMPILER_MSVC
+# pragma warning (push)
+# pragma warning (disable: 4996)
+#endif
+
+int ShinyManager_output(ShinyManager *self, const char *a_filename) {
+ if (!a_filename) {
+ ShinyManager_outputToStream(self, stdout);
+
+ } else {
+ FILE *file = fopen(a_filename, "w");
+ if (!file) return FALSE;
+ ShinyManager_outputToStream(self, file);
+ fclose(file);
+ }
+
+ return TRUE;
+}
+
+#if SHINY_COMPILER == SHINY_COMPILER_MSVC
+# pragma warning (pop)
+#endif
+
+
+/*---------------------------------------------------------------------------*/
+
+void ShinyManager_outputToStream(ShinyManager *self, FILE *a_stream) {
+ const char *error = ShinyManager_getOutputErrorString(self);
+
+ if (error) {
+ fwrite(error, 1, strlen(error), a_stream);
+ fwrite("\n\n", 1, 2, a_stream);
+ return;
+ }
+
+#if SHINY_OUTPUT_MODE & SHINY_OUTPUT_MODE_FLAT
+ ShinyManager_sortZones(self);
+
+ {
+ 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->nodeCount);
+ 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 /* SLIC3R_PROFILE */