00001 /* 00002 * Copyright 1999-2004 The Apache Software Foundation. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #if !defined(REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680) 00018 #define REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680 00019 00020 00021 00022 #include <algorithm> 00023 00024 00025 00026 #include "ReusableArenaBlock.hpp" 00027 #include "ArenaAllocator.hpp" 00028 00029 00030 00031 XALAN_CPP_NAMESPACE_BEGIN 00032 00033 00034 00035 template<class ObjectType> 00036 class ReusableArenaAllocator : public ArenaAllocator<ObjectType, 00037 ReusableArenaBlock<ObjectType> > 00038 { 00039 public: 00040 00041 typedef ReusableArenaBlock<ObjectType> ReusableArenaBlockType; 00042 00043 typedef typename ReusableArenaBlockType::size_type size_type; 00044 00045 typedef ArenaAllocator<ObjectType, 00046 ReusableArenaBlockType> BaseClassType; 00047 00048 typedef ReusableArenaAllocator<ObjectType> ThisType; 00049 00050 typedef XalanList<ReusableArenaBlockType*> ArenaBlockListType; 00051 00052 typedef typename ArenaBlockListType::iterator iterator; 00053 typedef typename ArenaBlockListType::const_iterator const_iterator; 00054 typedef typename ArenaBlockListType::reverse_iterator reverse_iterator; 00055 typedef typename ArenaBlockListType::const_reverse_iterator const_reverse_iterator; 00056 00057 00058 /* 00059 * Construct an instance that will allocate blocks of the specified size. 00060 * 00061 * @param theBlockSize The block size. 00062 */ 00063 ReusableArenaAllocator( 00064 MemoryManagerType& theManager, 00065 size_type theBlockSize, 00066 bool destroyBlocks = false) : 00067 BaseClassType(theManager, theBlockSize), 00068 m_destroyBlocks(destroyBlocks) 00069 { 00070 } 00071 00072 virtual 00073 ~ReusableArenaAllocator() 00074 { 00075 } 00076 00077 /* 00078 * Destroy the object, and free the block for re-use. 00079 * 00080 * @param theObject the address of the object. 00081 * @return true if the object was deleted, false if not. 00082 */ 00083 bool 00084 destroyObject(ObjectType* theObject) 00085 { 00086 bool bResult = false; 00087 00088 assert ( theObject != 0 ); 00089 00090 if ( this->m_blocks.empty() ) 00091 return bResult; 00092 00093 iterator iTerator = this->m_blocks.begin(); 00094 00095 iterator iEnd = this->m_blocks.end(); 00096 00097 // first , run over unfull blocks ( that consentrated from the head ) 00098 while( iTerator != iEnd 00099 && (*iTerator)->blockAvailable() ) 00100 { 00101 if ((*iTerator)->ownsBlock(theObject) == true) 00102 { 00103 (*iTerator)->destroyObject(theObject); 00104 00105 // move the block we have just deleted to the head of the list 00106 if (iTerator != this->m_blocks.begin()) 00107 { 00108 // move the block to the beginning 00109 ReusableArenaBlockType* block = *iTerator; 00110 00111 assert(block != 0); 00112 00113 this->m_blocks.erase(iTerator); 00114 00115 this->m_blocks.push_front(block); 00116 } 00117 00118 if (m_destroyBlocks) 00119 { 00120 destroyBlock(); 00121 } 00122 00123 bResult = true; 00124 00125 break; 00126 } 00127 00128 ++iTerator; 00129 } 00130 00131 reverse_iterator rIterator = this->m_blocks.rbegin(); 00132 00133 reverse_iterator rEnd = this->m_blocks.rend(); 00134 00135 // if the block hasn't been found from the head , start with full blocks ( from the taile) 00136 while ( !bResult && rIterator != rEnd ) 00137 { 00138 if ((*rIterator)->ownsBlock(theObject)) 00139 { 00140 (*rIterator)->destroyObject(theObject); 00141 00142 if (rIterator != this->m_blocks.rbegin()) 00143 { 00144 // move the block to the beginning 00145 ReusableArenaBlockType* block = *iTerator; 00146 00147 assert(block != 0); 00148 00149 this->m_blocks.erase(iTerator); 00150 00151 this->m_blocks.push_front(block); 00152 00153 } 00154 00155 if (m_destroyBlocks) 00156 { 00157 destroyBlock(); 00158 } 00159 00160 bResult = true; 00161 00162 break; 00163 } 00164 00165 if ( *rIterator == *iTerator) 00166 { 00167 break; 00168 } 00169 else 00170 { 00171 ++rIterator; 00172 } 00173 } 00174 00175 return bResult; 00176 00177 assert ( bResult ); 00178 } 00179 00180 /* 00181 * Allocate a block of the appropriate size for an 00182 * object. Call commitAllocation() when after 00183 * the object is successfully constructed. You _must_ 00184 * commit an allocation before performing any other 00185 * operation on the allocator. 00186 * 00187 * 00188 * @return A pointer to a block of memory 00189 */ 00190 virtual ObjectType* 00191 allocateBlock() 00192 { 00193 if( this->m_blocks.empty() 00194 || !this->m_blocks.front()->blockAvailable() ) 00195 { 00196 this->m_blocks.push_front( 00197 ReusableArenaBlockType::create( 00198 this->getMemoryManager(), 00199 this->m_blockSize)); 00200 00201 assert( this->m_blocks.front() != 0 ); 00202 } 00203 00204 assert( this->m_blocks.front() != 0 ); 00205 assert( this->m_blocks.front()->blockAvailable() ); 00206 00207 return this->m_blocks.front()->allocateBlock(); 00208 } 00209 00210 /* 00211 * Commits the allocation of the previous 00212 * allocateBlock() call. 00213 * 00214 * @param theObject A pointer to a block of memory 00215 */ 00216 virtual void 00217 commitAllocation(ObjectType* theObject) 00218 { 00219 // Note that this-> is required by template lookup rules. 00220 assert( this->m_blocks.empty() == false ); 00221 assert( this->m_blocks.front() != 0 ); 00222 assert( this->m_blocks.front()->ownsBlock(theObject) == true ); 00223 00224 this->m_blocks.front()->commitAllocation(theObject); 00225 00226 if( !this->m_blocks.front()->blockAvailable() ) 00227 { 00228 ReusableArenaBlockType* fullBlock = this->m_blocks.front(); 00229 00230 assert ( fullBlock != 0 ); 00231 00232 this->m_blocks.pop_front(); 00233 00234 this->m_blocks.push_back( fullBlock ); 00235 } 00236 } 00237 00238 00239 virtual bool 00240 ownsObject(const ObjectType* theObject) const 00241 { 00242 if ( this->m_blocks.empty() ) 00243 return false; 00244 00245 const_iterator iTerator = this->m_blocks.begin(); 00246 00247 const_iterator iEnd = this->m_blocks.end(); 00248 00249 while( iTerator != iEnd 00250 && (*iTerator)->blockAvailable() ) 00251 { 00252 if ((*iTerator)->ownsBlock(theObject) ) 00253 { 00254 return true; 00255 } 00256 00257 ++iTerator; 00258 } 00259 00260 const_reverse_iterator rIterator = this->m_blocks.rbegin(); 00261 00262 const_reverse_iterator rEnd = this->m_blocks.rend(); 00263 00264 while( rIterator != rEnd ) 00265 { 00266 if ((*rIterator)->ownsBlock(theObject) ) 00267 { 00268 return true; 00269 } 00270 00271 if ( *iTerator == *rIterator ) 00272 { 00273 break; 00274 } 00275 else 00276 { 00277 ++rIterator; 00278 } 00279 } 00280 00281 return false; 00282 } 00283 00284 protected: 00285 00286 /* 00287 * The method destroys an empty block from the head of the list. 00288 * For eliminating multiple create/destroy operation, the block 00289 * is destroyed only if the second one is not full. 00290 */ 00291 void 00292 destroyBlock() 00293 { 00294 assert(m_destroyBlocks == true); 00295 00296 if ( this->m_blocks.empty() == false) 00297 { 00298 const_iterator iTerator = this->m_blocks.begin(); 00299 00300 if ( (*iTerator)->isEmpty() ) 00301 { 00302 ++iTerator; 00303 00304 if (iTerator == this->m_blocks.end() || 00305 (*iTerator)->blockAvailable() ) 00306 { 00307 this->m_blocks.pop_front(); 00308 } 00309 } 00310 } 00311 } 00312 00313 // data members 00314 const bool m_destroyBlocks; 00315 00316 private: 00317 00318 // Not defined... 00319 ReusableArenaAllocator(const ReusableArenaAllocator<ObjectType>&); 00320 00321 ReusableArenaAllocator<ObjectType>& 00322 operator=(const ReusableArenaAllocator<ObjectType>&); 00323 00324 bool 00325 operator==(const ReusableArenaAllocator<ObjectType>&) const; 00326 }; 00327 00328 00329 00330 XALAN_CPP_NAMESPACE_END 00331 00332 00333 00334 #endif // !defined(REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680)
Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.
Xalan-C++ XSLT Processor Version 1.10 |
|