Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.10

Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ReusableArenaBlock.hpp

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

Interpreting class diagrams

Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.

dot

Xalan-C++ XSLT Processor Version 1.10
Copyright © 1999-2004 The Apache Software Foundation. All Rights Reserved.

Apache Logo