#include "../config/pathan_config.h" /* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "../simpleVariables/VarStoreImpl.hpp" #include "../simpleVariables/VarTypeStoreImpl.hpp" #include "../functionAPI/FunctionLookupImpl.hpp" #include // for datatype-uri #include "../items/impl/NodeImpl.hpp" #include ProxyMemoryManager::ProxyMemoryManager(XERCES_CPP_NAMESPACE_QUALIFIER MemoryManager *parent) : parent_(parent) { initialise(); } ProxyMemoryManager::~ProxyMemoryManager() { releaseAll(); } void ProxyMemoryManager::reset() { releaseAll(); initialise(); } void ProxyMemoryManager::initialise() { fCurrentBlock = 0; fToBeReleased = 0; fStringPool = new (this) StringPool(17, false, this); } void ProxyMemoryManager::releaseAll() { // Delete the heap for this document. This uncerimoniously yanks the storage // out from under all of the nodes in the document. Destructors are NOT called. ItemList *prev; while(fToBeReleased) { fToBeReleased->item->release(); prev = fToBeReleased->prev; delete fToBeReleased; fToBeReleased = prev; } // Run backwards through the linked list, deleting the blocks of memory while(fCurrentBlock) { MemList *prev = fCurrentBlock->prev; parent_->deallocate((char *)fCurrentBlock); fCurrentBlock = prev; } } void *ProxyMemoryManager::allocate(size_t amount) { char *newBlock = 0; try { newBlock = (char*)parent_->allocate(amount + sizeof(MemList)); } catch (...) {} if(!newBlock) { //ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory); throw PathanException(PathanException::RUNTIME_ERR, X("ProxyMemoryManager::allocate(): Out of memory")); } MemList *newMemList = (MemList *)newBlock; newMemList->prev = fCurrentBlock; newMemList->next = 0; if(fCurrentBlock) { fCurrentBlock->next = newMemList; } fCurrentBlock = newMemList; return (void *)(newBlock + sizeof(MemList)); } void ProxyMemoryManager::deallocate(void* p) { if(p) { char *oldBlock = ((char *)p) - sizeof(MemList); MemList *oldMemList = (MemList *)oldBlock; // Decouple the old block from the list if(oldMemList->prev) { oldMemList->prev->next = oldMemList->next; } if(oldMemList->next) { oldMemList->next->prev = oldMemList->prev; } else { // If the old block doesn't have a next, it must currently be fCurrentBlock fCurrentBlock = oldMemList->prev; } parent_->deallocate(oldBlock); } } void ProxyMemoryManager::markForRelease(Item* p) { ItemList *newEntry = new ItemList; newEntry->item = p; newEntry->prev = fToBeReleased; fToBeReleased = newEntry; } const XMLCh *ProxyMemoryManager::getPooledString(const XMLCh *src) { if(!src) return 0; // strings longer than 128 bytes are not pooled, as it is not probable they can be recycled if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(src) > 128) return XERCES_CPP_NAMESPACE_QUALIFIER XMLString::replicate(src, this); const XMLCh *found = fStringPool->get(src); if(found) { return found; } else { XMLCh *cloned = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::replicate(src, this); fStringPool->put(cloned, cloned); return cloned; } } const XMLCh *ProxyMemoryManager::getPooledString(const char *src) { if(!src) return 0; XMLCh *transcoded = XERCES_CPP_NAMESPACE_QUALIFIER XMLString::transcode(src, this); if(!transcoded) return 0; // strings longer than 128 bytes are not pooled, as it is not probable they can be recycled if(XERCES_CPP_NAMESPACE_QUALIFIER XMLString::stringLen(transcoded) > 128) return transcoded; const XMLCh *found = fStringPool->get(transcoded); if(found) { deallocate(transcoded); return found; } else { fStringPool->put(transcoded, transcoded); return transcoded; } } void ProxyMemoryManager::dumpStatistics() { std::cout << "Memory statistics:" << std::endl; StringPoolEnumerator e(fStringPool); unsigned int nStringCount = 0; while(e.hasMoreElements()) { e.nextElement(); ++nStringCount; } std::cout << "\tStrings in pool: " << nStringCount << std::endl; ItemList *pItemCursor = fToBeReleased; unsigned int nItemCount = 0; while(pItemCursor) { ++nItemCount; pItemCursor = pItemCursor->prev; } std::cout << "\tItems to be released: " << nItemCount << std::endl; MemList* pBlockCursor = fCurrentBlock; unsigned int nBlockCount=0; while(pBlockCursor) { ++nBlockCount; pBlockCursor = pBlockCursor->prev; } std::cout << "\tAllocated objects: " << nBlockCount << std::endl; } const Node* ProxyMemoryManager::createNode(const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *newNode) { return new (this) NodeImpl(newNode, this); } /** create a context with parameters */ DynamicContext* ProxyMemoryManager::createContext(XERCES_CPP_NAMESPACE_QUALIFIER XMLGrammarPool* xmlgr) { return new (this) XPath2ContextImpl(this, xmlgr, 0); } /** create a collation */ Collation* ProxyMemoryManager::createCollation(CollationHelper* helper) { return new (this) CollationImpl(this,helper); } /** create a resolver */ PathanNSResolver* ProxyMemoryManager::createNSResolver(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *resolverNode) { return new (this) PathanNSResolverImpl(this, resolverNode); } /** create a store for variables */ VariableStore* ProxyMemoryManager::createVariableStore() { return new (this) VarStoreImpl(this); } /** create a store for variables */ VariableTypeStore* ProxyMemoryManager::createVariableTypeStore() { return new (this) VarTypeStoreImpl(this); } /** create a function table */ FunctionLookup* ProxyMemoryManager::createFunctionTable() { return new (this) FunctionLookupImpl(this); }