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

ReusableArenaAllocator.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(REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680)
00018 #define REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680
00019 
00020 
00021 
00022 #include <algorithm>
00023 
00024 
00025 
00026 #include "ReusableArenaBlock.hpp"
00027 #include "ArenaAllocator.hpp"
00028 
00029 
00030 
00031 XALAN_CPP_NAMESPACE_BEGIN
00032 
00033 
00034 
00035 template<class ObjectType>
00036 class ReusableArenaAllocator : public ArenaAllocator<ObjectType,
00037                                                      ReusableArenaBlock<ObjectType> >
00038 {
00039 public:
00040 
00041     typedef ReusableArenaBlock<ObjectType>              ReusableArenaBlockType;
00042 
00043     typedef typename ReusableArenaBlockType::size_type  size_type;
00044 
00045     typedef ArenaAllocator<ObjectType,
00046                            ReusableArenaBlockType>      BaseClassType;
00047 
00048     typedef ReusableArenaAllocator<ObjectType>          ThisType;
00049 
00050     typedef XalanList<ReusableArenaBlockType*>          ArenaBlockListType;
00051 
00052     typedef typename ArenaBlockListType::iterator               iterator;
00053     typedef typename ArenaBlockListType::const_iterator         const_iterator;
00054     typedef typename ArenaBlockListType::reverse_iterator       reverse_iterator;
00055     typedef typename ArenaBlockListType::const_reverse_iterator const_reverse_iterator;
00056 
00057 
00058     /*
00059      * Construct an instance that will allocate blocks of the specified size.
00060      *
00061      * @param theBlockSize The block size.
00062      */
00063     ReusableArenaAllocator(
00064                 MemoryManagerType&  theManager,
00065                 size_type           theBlockSize, 
00066                 bool                destroyBlocks = false) :
00067         BaseClassType(theManager, theBlockSize),
00068         m_destroyBlocks(destroyBlocks)
00069     {
00070     }
00071 
00072     virtual
00073     ~ReusableArenaAllocator()
00074     {
00075     }
00076 
00077     /*
00078      * Destroy the object, and free the block for re-use.
00079      *
00080      * @param theObject the address of the object.
00081      * @return true if the object was deleted, false if not.
00082      */
00083     bool
00084     destroyObject(ObjectType*   theObject)
00085     {
00086         bool bResult = false;
00087 
00088         assert ( theObject != 0 );
00089 
00090         if ( this->m_blocks.empty() )
00091             return bResult;
00092 
00093         iterator iTerator = this->m_blocks.begin();
00094 
00095         iterator iEnd = this->m_blocks.end();
00096 
00097         // first , run over unfull blocks ( that consentrated from the head )
00098         while( iTerator != iEnd 
00099                     && (*iTerator)->blockAvailable() )
00100         {
00101             if ((*iTerator)->ownsBlock(theObject) == true)
00102             {
00103                 (*iTerator)->destroyObject(theObject);
00104                 
00105                 // move the block we have just deleted to the head of the list
00106                 if (iTerator != this->m_blocks.begin())
00107                 {
00108                     // move the block to the beginning
00109                     ReusableArenaBlockType* block = *iTerator;
00110 
00111                     assert(block != 0);
00112                     
00113                     this->m_blocks.erase(iTerator);
00114 
00115                     this->m_blocks.push_front(block);
00116                 }
00117 
00118                 if (m_destroyBlocks)
00119                 {
00120                     destroyBlock();
00121                 }
00122 
00123                 bResult = true;
00124 
00125                 break;
00126             }
00127 
00128             ++iTerator;
00129         }
00130 
00131         reverse_iterator rIterator = this->m_blocks.rbegin();
00132 
00133         reverse_iterator rEnd = this->m_blocks.rend();
00134 
00135         // if the block hasn't been found from the head , start with full blocks ( from the taile)
00136         while ( !bResult && rIterator != rEnd )
00137         {
00138             if ((*rIterator)->ownsBlock(theObject))
00139             {
00140                 (*rIterator)->destroyObject(theObject);
00141 
00142                 if (rIterator != this->m_blocks.rbegin())
00143                 {
00144                     // move the block to the beginning
00145                     ReusableArenaBlockType* block = *iTerator;
00146 
00147                     assert(block != 0);
00148                     
00149                     this->m_blocks.erase(iTerator);
00150 
00151                     this->m_blocks.push_front(block);
00152 
00153                 }
00154 
00155                 if (m_destroyBlocks)
00156                 {
00157                     destroyBlock();
00158                 }
00159 
00160                 bResult = true;
00161 
00162                 break; 
00163             }
00164 
00165             if ( *rIterator == *iTerator)
00166             {
00167                 break;
00168             }
00169             else
00170             {
00171                 ++rIterator;
00172             }
00173         }
00174 
00175         return bResult;
00176 
00177         assert ( bResult );
00178     }
00179 
00180     /*
00181      * Allocate a block of the appropriate size for an
00182      * object.  Call commitAllocation() when after
00183      * the object is successfully constructed.  You _must_
00184      * commit an allocation before performing any other
00185      * operation on the allocator.
00186      * 
00187      *
00188      * @return A pointer to a block of memory
00189      */
00190     virtual ObjectType*
00191     allocateBlock()
00192     {
00193         if( this->m_blocks.empty() 
00194             || !this->m_blocks.front()->blockAvailable() )
00195         {
00196             this->m_blocks.push_front(
00197                 ReusableArenaBlockType::create(
00198                     this->getMemoryManager(),
00199                     this->m_blockSize));
00200             
00201             assert( this->m_blocks.front() != 0 );
00202         }
00203 
00204         assert( this->m_blocks.front() != 0 );
00205         assert( this->m_blocks.front()->blockAvailable() );
00206 
00207         return this->m_blocks.front()->allocateBlock();
00208     }
00209 
00210     /*
00211      * Commits the allocation of the previous
00212      * allocateBlock() call.
00213      *
00214      * @param theObject A pointer to a block of memory
00215      */
00216     virtual void
00217     commitAllocation(ObjectType*    theObject)
00218     {
00219         // Note that this-> is required by template lookup rules.
00220         assert( this->m_blocks.empty() == false );
00221         assert( this->m_blocks.front() != 0 );
00222         assert( this->m_blocks.front()->ownsBlock(theObject) == true );
00223 
00224         this->m_blocks.front()->commitAllocation(theObject);
00225 
00226         if( !this->m_blocks.front()->blockAvailable() )
00227         {
00228             ReusableArenaBlockType* fullBlock = this->m_blocks.front();
00229 
00230             assert ( fullBlock != 0 );
00231 
00232             this->m_blocks.pop_front();
00233 
00234             this->m_blocks.push_back( fullBlock );
00235         }
00236     }
00237 
00238 
00239     virtual bool
00240     ownsObject(const ObjectType*    theObject) const
00241     {
00242         if ( this->m_blocks.empty() )
00243             return false;
00244 
00245         const_iterator iTerator = this->m_blocks.begin();
00246 
00247         const_iterator iEnd = this->m_blocks.end();
00248 
00249         while( iTerator != iEnd 
00250                     && (*iTerator)->blockAvailable() )
00251         {
00252             if ((*iTerator)->ownsBlock(theObject) )
00253             {
00254                 return true;
00255             }
00256 
00257             ++iTerator;
00258         }
00259 
00260         const_reverse_iterator rIterator = this->m_blocks.rbegin();
00261 
00262         const_reverse_iterator rEnd = this->m_blocks.rend();
00263 
00264         while( rIterator != rEnd )
00265         {
00266             if ((*rIterator)->ownsBlock(theObject) )
00267             {
00268                 return true;
00269             }
00270 
00271             if ( *iTerator == *rIterator )
00272             {
00273                 break;
00274             }
00275             else
00276             {
00277                 ++rIterator;
00278             }
00279         }
00280 
00281         return false;
00282     }
00283 
00284 protected:
00285 
00286     /*
00287      * The method destroys an empty block from the head of the list.
00288      * For eliminating multiple create/destroy operation, the block
00289      * is destroyed only if the second one is not full.
00290      */
00291     void
00292     destroyBlock()
00293     {
00294         assert(m_destroyBlocks == true);
00295 
00296         if ( this->m_blocks.empty() == false)
00297         {
00298             const_iterator iTerator = this->m_blocks.begin();
00299 
00300             if ( (*iTerator)->isEmpty() )
00301             {
00302                 ++iTerator;
00303 
00304                 if (iTerator == this->m_blocks.end() ||
00305                     (*iTerator)->blockAvailable() )
00306                 {
00307                     this->m_blocks.pop_front();
00308                 }
00309             }
00310         }
00311     }
00312 
00313     // data members
00314     const bool  m_destroyBlocks;
00315 
00316 private:
00317 
00318     // Not defined...
00319     ReusableArenaAllocator(const ReusableArenaAllocator<ObjectType>&);
00320 
00321     ReusableArenaAllocator<ObjectType>&
00322     operator=(const ReusableArenaAllocator<ObjectType>&);
00323 
00324     bool
00325     operator==(const ReusableArenaAllocator<ObjectType>&) const;
00326 };
00327 
00328 
00329 
00330 XALAN_CPP_NAMESPACE_END
00331 
00332 
00333 
00334 #endif  // !defined(REUSABLEARENAALLOCATOR_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.