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.