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