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(REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680) 00020 #define REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680 00021 00022 00023 #include <xalanc/PlatformSupport/ArenaBlockBase.hpp> 00024 00025 00026 00027 #include <xalanc/Include/XalanMemMgrAutoPtr.hpp> 00028 00029 00030 00031 XALAN_CPP_NAMESPACE_BEGIN 00032 00033 00034 00035 template <class ObjectType, 00036 #if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS) 00037 class SizeType> 00038 #else 00039 class SizeType = unsigned short> 00040 #endif 00041 class ReusableArenaBlock : public ArenaBlockBase<ObjectType, SizeType> 00042 { 00043 00044 public: 00045 00046 typedef ArenaBlockBase<ObjectType, SizeType> BaseClassType; 00047 00048 typedef typename BaseClassType::size_type size_type; 00049 00050 typedef ReusableArenaBlock<ObjectType, SizeType> ThisType; 00051 00052 struct NextBlock 00053 { 00054 enum { VALID_OBJECT_STAMP = 0xffddffdd }; 00055 00056 size_type next; 00057 const int verificationStamp; 00058 00059 NextBlock( size_type _next): 00060 next(_next), 00061 verificationStamp(VALID_OBJECT_STAMP) 00062 { 00063 } 00064 00065 bool 00066 isValidFor( size_type rightBorder ) const 00067 { 00068 return ( ( verificationStamp == int(VALID_OBJECT_STAMP)) && 00069 ( next <= rightBorder ) ) ? true : false ; 00070 } 00071 }; 00072 00073 /* 00074 * Construct an ArenaBlock of the specified size 00075 * of objects. 00076 * 00077 * @param theBlockSize The size of the block (the 00078 * number of objects it can contain). 00079 */ 00080 ReusableArenaBlock( 00081 MemoryManager& theManager, 00082 size_type theBlockSize) : 00083 BaseClassType(theManager, theBlockSize), 00084 m_firstFreeBlock(0), 00085 m_nextFreeBlock(0) 00086 00087 { 00088 XALAN_STATIC_ASSERT(sizeof(ObjectType) >= sizeof(NextBlock)); 00089 00090 for( size_type i = 0; i < this->m_blockSize; ++i ) 00091 { 00092 new (&this->m_objectBlock[i]) NextBlock(size_type(i + 1)); 00093 } 00094 } 00095 00096 ~ReusableArenaBlock() 00097 { 00098 size_type removedObjects = 0; 00099 00100 for (size_type i = 0; 00101 i < this->m_blockSize && 00102 removedObjects < this->m_objectCount; 00103 ++i) 00104 { 00105 if ( isOccupiedBlock(&this->m_objectBlock[i]) ) 00106 { 00107 this->m_objectBlock[i].~ObjectType(); 00108 00109 ++removedObjects; 00110 } 00111 } 00112 } 00113 00114 static ThisType* 00115 create( 00116 MemoryManager& theManager, 00117 size_type theBlockSize) 00118 { 00119 ThisType* theInstance; 00120 00121 return XalanConstruct( 00122 theManager, 00123 theInstance, 00124 theManager, 00125 theBlockSize); 00126 } 00127 00128 /* 00129 * Allocate a block. Once the object is constructed, you must call 00130 * commitAllocation(). 00131 * 00132 * @return a pointer to the new block. 00133 */ 00134 ObjectType* 00135 allocateBlock() 00136 { 00137 if ( this->m_objectCount == this->m_blockSize ) 00138 { 00139 assert ( this->m_firstFreeBlock == (this->m_blockSize + 1) ); 00140 00141 return 0; 00142 } 00143 else 00144 { 00145 assert( this->m_objectCount < this->m_blockSize ); 00146 00147 ObjectType* theResult = 0; 00148 00149 assert ( this->m_firstFreeBlock <= this->m_blockSize ); 00150 assert ( this->m_nextFreeBlock <= this->m_blockSize ); 00151 00152 // check if any part was allocated but not commited 00153 if(this->m_firstFreeBlock != this->m_nextFreeBlock) 00154 { 00155 // return the previously allocated block and wait for a commit 00156 theResult = this->m_objectBlock + this->m_firstFreeBlock; 00157 } 00158 else 00159 { 00160 theResult = this->m_objectBlock + this->m_firstFreeBlock; 00161 00162 assert(size_type(theResult - this->m_objectBlock) < this->m_blockSize); 00163 00164 NextBlock* const theBlock = 00165 reinterpret_cast<NextBlock*>(theResult); 00166 00167 this->m_nextFreeBlock = theBlock->next; 00168 00169 assert(theBlock->isValidFor(this->m_blockSize)); 00170 assert(this->m_nextFreeBlock <= this->m_blockSize); 00171 00172 ++this->m_objectCount; 00173 } 00174 00175 return theResult; 00176 } 00177 } 00178 00179 /* 00180 * Commit the previous allocation. 00181 * 00182 * @param theBlock the address that was returned by allocateBlock() 00183 */ 00184 void 00185 commitAllocation(ObjectType* /* theBlock */) 00186 { 00187 assert ( this->m_objectCount <= this->m_blockSize ); 00188 00189 this->m_firstFreeBlock = this->m_nextFreeBlock; 00190 } 00191 00192 /* 00193 * Destroy the object, and return the block to the free list. 00194 * The behavior is undefined if the object pointed to is not 00195 * owned by the block. 00196 * 00197 * @param theObject the address of the object. 00198 */ 00199 void 00200 destroyObject(ObjectType* theObject) 00201 { 00202 assert(theObject != 0); 00203 00204 // check if any uncommited block is there, add it to the list 00205 if ( this->m_firstFreeBlock != this->m_nextFreeBlock ) 00206 { 00207 // Return it to the pool of free blocks 00208 void* const p = this->m_objectBlock + this->m_firstFreeBlock; 00209 00210 new (p) NextBlock(this->m_nextFreeBlock); 00211 00212 this->m_nextFreeBlock = this->m_firstFreeBlock; 00213 } 00214 00215 assert(ownsObject(theObject) == true); 00216 assert(shouldDestroyBlock(theObject)); 00217 00218 XalanDestroy(*theObject); 00219 00220 new (theObject) NextBlock(this->m_firstFreeBlock); 00221 00222 m_firstFreeBlock = 00223 this->m_nextFreeBlock = 00224 size_type(theObject - this->m_objectBlock); 00225 00226 assert (this->m_firstFreeBlock <= this->m_blockSize); 00227 00228 --this->m_objectCount; 00229 } 00230 00231 /* 00232 * Determine if this block owns the specified object. Note 00233 * that even if the object address is within our block, this 00234 * call will return false if no object currently occupies the 00235 * block. See also ownsBlock(). 00236 * 00237 * @param theObject the address of the object. 00238 * @return true if we own the object, false if not. 00239 */ 00240 bool 00241 ownsObject(const ObjectType* theObject) const 00242 { 00243 assert ( theObject != 0 ); 00244 00245 return isOccupiedBlock(theObject); 00246 } 00247 00248 protected: 00249 00250 /* 00251 * Determine if the block should be destroyed. Returns true, 00252 * unless the object is on the free list. The behavior is 00253 * undefined if the object pointed to is not owned by the 00254 * block. 00255 * 00256 * @param theObject the address of the object 00257 * @return true if block should be destroyed, false if not. 00258 */ 00259 bool 00260 shouldDestroyBlock(const ObjectType* theObject) const 00261 { 00262 assert(size_type(theObject - this->m_objectBlock) < this->m_blockSize); 00263 00264 return !isOnFreeList(theObject); 00265 } 00266 00267 bool 00268 isOccupiedBlock(const ObjectType* block) const 00269 { 00270 assert( block !=0 ); 00271 00272 return !(this->ownsBlock(block) && 00273 reinterpret_cast<const NextBlock*>(block)->isValidFor(this->m_blockSize)); 00274 } 00275 00276 private: 00277 00278 // Not implemented... 00279 ReusableArenaBlock(const ReusableArenaBlock<ObjectType, SizeType>&); 00280 00281 ReusableArenaBlock<ObjectType, SizeType>& 00282 operator=(const ReusableArenaBlock<ObjectType, SizeType>&); 00283 00284 bool 00285 operator==(const ReusableArenaBlock<ObjectType, SizeType>&) const; 00286 00287 00288 /* 00289 * Determine if the block is on the free list. The behavior is 00290 * undefined if the object pointed to is not owned by the 00291 * block. 00292 * 00293 * @param theObject the address of the object 00294 * @return true if block is on the free list, false if not. 00295 */ 00296 bool 00297 isOnFreeList(const ObjectType* theObject) const 00298 { 00299 if ( this->m_objectCount == 0 ) 00300 { 00301 return false; 00302 } 00303 else 00304 { 00305 ObjectType* pRunPtr = this->m_objectBlock + this->m_firstFreeBlock; 00306 00307 for (size_type i = 0; 00308 i < this->m_blockSize - this->m_objectCount; 00309 ++i) 00310 { 00311 assert(this->ownsBlock(pRunPtr)); 00312 00313 if (pRunPtr == theObject) 00314 { 00315 return true; 00316 } 00317 else 00318 { 00319 NextBlock* const p = reinterpret_cast<NextBlock*>(pRunPtr); 00320 00321 assert(p->isValidFor(this->m_blockSize)); 00322 00323 pRunPtr = this->m_objectBlock + p->next; 00324 } 00325 } 00326 00327 return false; 00328 } 00329 } 00330 00331 // Data members... 00332 size_type m_firstFreeBlock; 00333 00334 size_type m_nextFreeBlock; 00335 }; 00336 00337 00338 00339 XALAN_CPP_NAMESPACE_END 00340 00341 00342 00343 #endif // !defined(REUSABLEARENABLOCK_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 |
|