mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 12:41:20 -06:00 
			
		
		
		
	 0558b53493
			
		
	
	
		0558b53493
		
	
	
	
	
		
			
			The XS was left only for the unit / integration tests, and it links libslic3r only. No wxWidgets are allowed to be used from Perl starting from now.
		
			
				
	
	
		
			445 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			445 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| 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 */
 |