## Xalan-C++ API Documentation

### The Xalan C++ XSLT Processor Version 1.9

Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

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

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.9 Copyright © 1999-2004 The Apache Software Foundation. All Rights Reserved.