## 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.

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