/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if !defined(REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680) #define REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680 #include #include "ReusableArenaBlock.hpp" #include "ArenaAllocator.hpp" namespace XALAN_CPP_NAMESPACE { template class ReusableArenaAllocator : public ArenaAllocator > { public: typedef ReusableArenaBlock ReusableArenaBlockType; typedef typename ReusableArenaBlockType::size_type size_type; typedef ArenaAllocator BaseClassType; typedef ReusableArenaAllocator ThisType; typedef XalanList ArenaBlockListType; typedef typename ArenaBlockListType::iterator iterator; typedef typename ArenaBlockListType::const_iterator const_iterator; typedef typename ArenaBlockListType::reverse_iterator reverse_iterator; typedef typename ArenaBlockListType::const_reverse_iterator const_reverse_iterator; /* * Construct an instance that will allocate blocks of the specified size. * * @param theBlockSize The block size. */ ReusableArenaAllocator( MemoryManager& theManager, size_type theBlockSize, bool destroyBlocks = false) : BaseClassType(theManager, theBlockSize), m_destroyBlocks(destroyBlocks) { } virtual ~ReusableArenaAllocator() { } /* * Destroy the object, and free the block for re-use. * * @param theObject the address of the object. * @return true if the object was deleted, false if not. */ bool destroyObject(ObjectType* theObject) { bool bResult = false; assert ( theObject != 0 ); if ( this->m_blocks.empty() ) return bResult; iterator iTerator = this->m_blocks.begin(); iterator iEnd = this->m_blocks.end(); // first , run over unfull blocks ( that consentrated from the head ) while( iTerator != iEnd && (*iTerator)->blockAvailable() ) { if ((*iTerator)->ownsBlock(theObject) == true) { (*iTerator)->destroyObject(theObject); // move the block we have just deleted to the head of the list if (iTerator != this->m_blocks.begin()) { // move the block to the beginning ReusableArenaBlockType* block = *iTerator; assert(block != 0); this->m_blocks.erase(iTerator); this->m_blocks.push_front(block); } if (m_destroyBlocks) { destroyBlock(); } bResult = true; break; } ++iTerator; } reverse_iterator rIterator = this->m_blocks.rbegin(); reverse_iterator rEnd = this->m_blocks.rend(); // if the block hasn't been found from the head , start with full blocks ( from the taile) while ( !bResult && rIterator != rEnd ) { if ((*rIterator)->ownsBlock(theObject)) { (*rIterator)->destroyObject(theObject); if (rIterator != this->m_blocks.rbegin()) { // move the block to the beginning ReusableArenaBlockType* block = *iTerator; assert(block != 0); this->m_blocks.erase(iTerator); this->m_blocks.push_front(block); } if (m_destroyBlocks) { destroyBlock(); } bResult = true; break; } if ( *rIterator == *iTerator) { break; } else { ++rIterator; } } return bResult; } /* * Allocate a block of the appropriate size for an * object. Call commitAllocation() when after * the object is successfully constructed. You _must_ * commit an allocation before performing any other * operation on the allocator. * * * @return A pointer to a block of memory */ virtual ObjectType* allocateBlock() { if( this->m_blocks.empty() || !this->m_blocks.front()->blockAvailable() ) { this->m_blocks.push_front( ReusableArenaBlockType::create( this->getMemoryManager(), this->m_blockSize)); assert( this->m_blocks.front() != 0 ); } assert( this->m_blocks.front() != 0 ); assert( this->m_blocks.front()->blockAvailable() ); return this->m_blocks.front()->allocateBlock(); } /* * Commits the allocation of the previous * allocateBlock() call. * * @param theObject A pointer to a block of memory */ virtual void commitAllocation(ObjectType* theObject) { // Note that this-> is required by template lookup rules. assert( this->m_blocks.empty() == false ); assert( this->m_blocks.front() != 0 ); assert( this->m_blocks.front()->ownsBlock(theObject) == true ); this->m_blocks.front()->commitAllocation(theObject); if( !this->m_blocks.front()->blockAvailable() ) { ReusableArenaBlockType* fullBlock = this->m_blocks.front(); assert ( fullBlock != 0 ); this->m_blocks.pop_front(); this->m_blocks.push_back( fullBlock ); } } virtual bool ownsObject(const ObjectType* theObject) const { if ( this->m_blocks.empty() ) return false; const_iterator iTerator = this->m_blocks.begin(); const_iterator iEnd = this->m_blocks.end(); while( iTerator != iEnd && (*iTerator)->blockAvailable() ) { if ((*iTerator)->ownsBlock(theObject) ) { return true; } ++iTerator; } const_reverse_iterator rIterator = this->m_blocks.rbegin(); const_reverse_iterator rEnd = this->m_blocks.rend(); while( rIterator != rEnd ) { if ((*rIterator)->ownsBlock(theObject) ) { return true; } if ( *iTerator == *rIterator ) { break; } else { ++rIterator; } } return false; } protected: /* * The method destroys an empty block from the head of the list. * For eliminating multiple create/destroy operation, the block * is destroyed only if the second one is not full. */ void destroyBlock() { assert(m_destroyBlocks == true); if ( this->m_blocks.empty() == false) { const_iterator iTerator = this->m_blocks.begin(); if ( (*iTerator)->isEmpty() ) { ++iTerator; if (iTerator == this->m_blocks.end() || (*iTerator)->blockAvailable() ) { this->m_blocks.pop_front(); } } } } // data members const bool m_destroyBlocks; private: // Not defined... ReusableArenaAllocator(const ReusableArenaAllocator&); ReusableArenaAllocator& operator=(const ReusableArenaAllocator&); bool operator==(const ReusableArenaAllocator&) const; }; } #endif // !defined(REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680)