00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one 00003 * or more contributor license agreements. See the NOTICE file 00004 * distributed with this work for additional information 00005 * regarding copyright ownership. The ASF licenses this file 00006 * to you under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 00019 #if !defined(REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680) 00020 #define REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680 00021 00022 00023 00024 #include <algorithm> 00025 00026 00027 00028 #include "ReusableArenaBlock.hpp" 00029 #include "ArenaAllocator.hpp" 00030 00031 00032 00033 XALAN_CPP_NAMESPACE_BEGIN 00034 00035 00036 00037 template<class ObjectType> 00038 class ReusableArenaAllocator : public ArenaAllocator<ObjectType, 00039 ReusableArenaBlock<ObjectType> > 00040 { 00041 public: 00042 00043 typedef ReusableArenaBlock<ObjectType> ReusableArenaBlockType; 00044 00045 typedef typename ReusableArenaBlockType::size_type size_type; 00046 00047 typedef ArenaAllocator<ObjectType, 00048 ReusableArenaBlockType> BaseClassType; 00049 00050 typedef ReusableArenaAllocator<ObjectType> ThisType; 00051 00052 typedef XalanList<ReusableArenaBlockType*> ArenaBlockListType; 00053 00054 typedef typename ArenaBlockListType::iterator iterator; 00055 typedef typename ArenaBlockListType::const_iterator const_iterator; 00056 typedef typename ArenaBlockListType::reverse_iterator reverse_iterator; 00057 typedef typename ArenaBlockListType::const_reverse_iterator const_reverse_iterator; 00058 00059 00060 /* 00061 * Construct an instance that will allocate blocks of the specified size. 00062 * 00063 * @param theBlockSize The block size. 00064 */ 00065 ReusableArenaAllocator( 00066 MemoryManager& theManager, 00067 size_type theBlockSize, 00068 bool destroyBlocks = false) : 00069 BaseClassType(theManager, theBlockSize), 00070 m_destroyBlocks(destroyBlocks) 00071 { 00072 } 00073 00074 virtual 00075 ~ReusableArenaAllocator() 00076 { 00077 } 00078 00079 /* 00080 * Destroy the object, and free the block for re-use. 00081 * 00082 * @param theObject the address of the object. 00083 * @return true if the object was deleted, false if not. 00084 */ 00085 bool 00086 destroyObject(ObjectType* theObject) 00087 { 00088 bool bResult = false; 00089 00090 assert ( theObject != 0 ); 00091 00092 if ( this->m_blocks.empty() ) 00093 return bResult; 00094 00095 iterator iTerator = this->m_blocks.begin(); 00096 00097 iterator iEnd = this->m_blocks.end(); 00098 00099 // first , run over unfull blocks ( that consentrated from the head ) 00100 while( iTerator != iEnd 00101 && (*iTerator)->blockAvailable() ) 00102 { 00103 if ((*iTerator)->ownsBlock(theObject) == true) 00104 { 00105 (*iTerator)->destroyObject(theObject); 00106 00107 // move the block we have just deleted to the head of the list 00108 if (iTerator != this->m_blocks.begin()) 00109 { 00110 // move the block to the beginning 00111 ReusableArenaBlockType* block = *iTerator; 00112 00113 assert(block != 0); 00114 00115 this->m_blocks.erase(iTerator); 00116 00117 this->m_blocks.push_front(block); 00118 } 00119 00120 if (m_destroyBlocks) 00121 { 00122 destroyBlock(); 00123 } 00124 00125 bResult = true; 00126 00127 break; 00128 } 00129 00130 ++iTerator; 00131 } 00132 00133 reverse_iterator rIterator = this->m_blocks.rbegin(); 00134 00135 reverse_iterator rEnd = this->m_blocks.rend(); 00136 00137 // if the block hasn't been found from the head , start with full blocks ( from the taile) 00138 while ( !bResult && rIterator != rEnd ) 00139 { 00140 if ((*rIterator)->ownsBlock(theObject)) 00141 { 00142 (*rIterator)->destroyObject(theObject); 00143 00144 if (rIterator != this->m_blocks.rbegin()) 00145 { 00146 // move the block to the beginning 00147 ReusableArenaBlockType* block = *iTerator; 00148 00149 assert(block != 0); 00150 00151 this->m_blocks.erase(iTerator); 00152 00153 this->m_blocks.push_front(block); 00154 00155 } 00156 00157 if (m_destroyBlocks) 00158 { 00159 destroyBlock(); 00160 } 00161 00162 bResult = true; 00163 00164 break; 00165 } 00166 00167 if ( *rIterator == *iTerator) 00168 { 00169 break; 00170 } 00171 else 00172 { 00173 ++rIterator; 00174 } 00175 } 00176 00177 return 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.11 |
|