Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.8

Main Page | Directories | 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 #include <vector>
00024 
00025 
00026 
00027 #include "ReusableArenaBlock.hpp"
00028 #include "ArenaAllocator.hpp"
00029 
00030 
00031 
00032 XALAN_CPP_NAMESPACE_BEGIN
00033 
00034 
00035 
00036 template<class ObjectType>
00037 class ReusableArenaAllocator : public ArenaAllocator<ObjectType,
00038                                                      ReusableArenaBlock<ObjectType> >
00039 {
00040 public:
00041 
00042     typedef ReusableArenaBlock<ObjectType>              ReusableArenaBlockType;
00043 
00044     typedef typename ReusableArenaBlockType::size_type  size_type;
00045 
00046     typedef ArenaAllocator<ObjectType,
00047                            ReusableArenaBlockType>      BaseClassType;
00048 
00049 #if defined (XALAN_NO_STD_NAMESPACE)
00050     typedef vector<ReusableArenaBlockType*>             ArenaBlockListType;
00051 #else
00052     typedef std::vector<ReusableArenaBlockType*>        ArenaBlockListType;
00053 #endif
00054 
00055     /*
00056      * Construct an instance that will allocate blocks of the specified size.
00057      *
00058      * @param theBlockSize The block size.
00059      */
00060     ReusableArenaAllocator(size_type    theBlockSize) :
00061         BaseClassType(theBlockSize),
00062         m_lastBlockReferenced(0)
00063     {
00064     }
00065 
00066     virtual
00067     ~ReusableArenaAllocator()
00068     {
00069     }
00070 
00071     /*
00072      * Destroy the object, and free the block for re-use.
00073      *
00074      * @param theObject the address of the object.
00075      * @return true if the object was deleted, false if not.
00076      */
00077     bool
00078     destroyObject(ObjectType*   theObject)
00079     {
00080         bool    fSuccess = false;
00081 
00082         // Check this, just in case...
00083         if (m_lastBlockReferenced != 0 && m_lastBlockReferenced->ownsObject(theObject) == true)
00084         {
00085             m_lastBlockReferenced->destroyObject(theObject);
00086 
00087             fSuccess = true;
00088         }
00089         else
00090         {
00091             // Note that this-> is required by template lookup rules.
00092             const typename ArenaBlockListType::reverse_iterator theEnd = this->m_blocks.rend();
00093 
00094             typename ArenaBlockListType::reverse_iterator   i = this->m_blocks.rbegin();
00095 
00096             while(i != theEnd)
00097             {
00098                 if ((*i)->ownsObject(theObject) == true)
00099                 {
00100                     m_lastBlockReferenced = *i;
00101 
00102                     m_lastBlockReferenced->destroyObject(theObject);
00103 
00104                     fSuccess = true;
00105 
00106                     break;
00107                 }
00108                 else
00109                 {
00110                     ++i;
00111                 }
00112             }
00113         }
00114 
00115         return fSuccess;
00116     }
00117 
00118     /*
00119      * Allocate a block of the appropriate size for an
00120      * object.  Call commitAllocation() when after
00121      * the object is successfully constructed.  You _must_
00122      * commit an allocation before performing any other
00123      * operation on the allocator.
00124      *
00125      * @return A pointer to a block of memory
00126      */
00127     virtual ObjectType*
00128     allocateBlock()
00129     {
00130         if (m_lastBlockReferenced == 0 ||
00131             m_lastBlockReferenced->blockAvailable() == false)
00132         {
00133             // Search back for a block with some space available...     
00134             const typename ArenaBlockListType::reverse_iterator theEnd = this->m_blocks.rend();
00135             
00136             // Note that this-> is required by template lookup rules.
00137             typename ArenaBlockListType::reverse_iterator   i = this->m_blocks.rbegin();
00138 
00139             while(i != theEnd)
00140             {
00141                 assert(*i != 0);
00142 
00143                 if (*i != m_lastBlockReferenced && (*i)->blockAvailable() == true)
00144                 {
00145                     // Ahh, found one with free space.
00146                     m_lastBlockReferenced = *i;
00147 
00148                     break;
00149                 }
00150                 else
00151                 {
00152                     ++i;
00153                 }
00154             }
00155 
00156             if (i == theEnd)
00157             {
00158                 // No blocks have free space available, so create a new block, and
00159                 // push it on the list.
00160                 // Note that this-> is required by template lookup rules.
00161                 m_lastBlockReferenced = new ReusableArenaBlockType(this->m_blockSize);
00162 
00163                 this->m_blocks.push_back(m_lastBlockReferenced);
00164             }
00165         }
00166         assert(m_lastBlockReferenced != 0 && m_lastBlockReferenced->blockAvailable() == true);
00167 
00168         return m_lastBlockReferenced->allocateBlock();
00169     }
00170 
00171     /*
00172      * Commits the allocation of the previous
00173      * allocateBlock() call.
00174      *
00175      * @param theObject A pointer to a block of memory
00176      */
00177     virtual void
00178     commitAllocation(ObjectType*    theObject)
00179     {
00180         // Note that this-> is required by template lookup rules.
00181         assert(this->m_blocks.empty() == false && m_lastBlockReferenced != 0 && m_lastBlockReferenced->ownsBlock(theObject) == true);
00182 
00183         m_lastBlockReferenced->commitAllocation(theObject);
00184         assert(m_lastBlockReferenced->ownsObject(theObject) == true);
00185     }
00186 
00187     virtual void
00188     reset()
00189     {
00190         m_lastBlockReferenced = 0;
00191 
00192         BaseClassType::reset();
00193     }
00194 
00195     virtual bool
00196     ownsObject(const ObjectType*    theObject) const
00197     {
00198         bool    fResult = false;
00199 
00200         // If no block has ever been referenced, then we haven't allocated
00201         // any objects.
00202         if (m_lastBlockReferenced != 0)
00203         {
00204             // Check the last referenced block first.
00205             fResult = m_lastBlockReferenced->ownsObject(theObject);
00206 
00207             if (fResult == false)
00208             {
00209                 fResult = BaseClassType::ownsObject(theObject);
00210             }
00211         }
00212 
00213         return fResult;
00214     }
00215 
00216 private:
00217 
00218     // Not defined...
00219     ReusableArenaAllocator(const ReusableArenaAllocator<ObjectType>&);
00220 
00221     ReusableArenaAllocator<ObjectType>&
00222     operator=(const ReusableArenaAllocator<ObjectType>&);
00223 
00224     // Data members...
00225     ReusableArenaBlockType*     m_lastBlockReferenced;
00226 };
00227 
00228 
00229 
00230 XALAN_CPP_NAMESPACE_END
00231 
00232 
00233 
00234 #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.8
Copyright © 1999-2004 The Apache Software Foundation. All Rights Reserved.