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