Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.10

Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

XalanArrayAllocator.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 #if !defined(XALANARRAYALLOCATOR_HEADER_GUARD_1357924680)
00017 #define XALANARRAYALLOCATOR_HEADER_GUARD_1357924680
00018 
00019 
00020 
00021 #include <xalanc/PlatformSupport/PlatformSupportDefinitions.hpp>
00022 
00023 
00024 
00025 #include <cassert>
00026 #include <utility>
00027 
00028 
00029 #include <xalanc/Include/XalanMemMgrHelper.hpp>
00030 #include <xalanc/Include/XalanVector.hpp>
00031 #include <xalanc/Include/XalanList.hpp>
00032 
00033 
00034 
00035 XALAN_CPP_NAMESPACE_BEGIN
00036 
00037 
00038 
00039 template<class Type>
00040 class XALAN_PLATFORMSUPPORT_EXPORT XalanArrayAllocator
00041 {
00042 public:
00043 
00044     typedef XalanVector<Type>               VectorType;
00045     typedef typename VectorType::size_type  size_type;
00046 
00047     typedef XALAN_STD_QUALIFIER pair<size_type, VectorType * >      ListEntryType;
00048     typedef XalanList<ListEntryType>                                ListType;
00049 
00050     typedef Type                            value_type;
00051 
00052     typedef typename ListType::iterator     ListIteratorType;
00053 
00054     // Default size for vector allocation.
00055     enum { eDefaultBlockSize = 500 };
00056 
00062     XalanArrayAllocator(MemoryManagerType&       theManager,
00063                         size_type   theBlockSize = eDefaultBlockSize) :
00064         m_list(theManager),
00065         m_blockSize(theBlockSize),
00066         m_lastEntryFound(0)
00067     {
00068     }
00069 
00070     ~XalanArrayAllocator()
00071     {        
00072         typename ListType::iterator iter = m_list.begin();
00073 
00074         MemoryManagerType& theManager = m_list.getMemoryManager();
00075 
00076         for( iter = m_list.begin(); iter != m_list.end(); ++iter)
00077         {
00078             if( (*iter).second != 0)
00079             {
00080 #if defined(XALAN_REQUIRES_QUALIFIED_DESTRUCTOR)
00081                 (*iter).second->VectorType::~VectorType();
00082 #else
00083                 (*iter).second->~VectorType();
00084 #endif               
00085                 theManager.deallocate((void*)(*iter).second);
00086             }
00087         }
00088     }
00089 
00093     void
00094     clear()
00095     {
00096         m_list.clear();
00097 
00098         m_lastEntryFound = 0;
00099     }
00100 
00106     void
00107     reset()
00108     {
00109         if (m_list.empty() == true)
00110         {
00111             m_lastEntryFound = 0;
00112         }
00113         else
00114         {
00115             const ListIteratorType  theEnd = m_list.end();
00116             ListIteratorType        theCurrent = m_list.begin();
00117 
00118             do
00119             {
00120                 (*theCurrent).first = (*theCurrent).second->size();
00121 
00122                 ++theCurrent;
00123             } while(theCurrent != theEnd);
00124 
00125             m_lastEntryFound = &*m_list.begin();
00126         }
00127     }
00128 
00135     Type*
00136     allocate(size_type  theCount)
00137     {
00138         // Handle the case of theCount being greater than the block size first...
00139         if (theCount >= m_blockSize)
00140         {
00141             return createEntry(theCount, theCount);
00142         }
00143         else
00144         {
00145             ListEntryType*  theEntry =
00146                 findEntry(theCount);
00147 
00148             // Did we find a slot?
00149             if (theEntry == 0)
00150             {
00151                 // Nope, create a new one...
00152                 return createEntry(m_blockSize, theCount);
00153             }
00154             else
00155             {
00156                 // The address we want is that of the first free element in the
00157                 // vector...
00158                 assert( theEntry->second != 0);
00159                 Type* const     thePointer =
00160                     &*theEntry->second->begin() + (theEntry->second->size() - theEntry->first);
00161 
00162                 // Resize the vector to the appropriate size...
00163                 theEntry->first -= theCount;
00164 
00165                 return thePointer;
00166             }
00167         }
00168     }
00169 
00170 private:
00171 
00172     // Utility functions...
00173     Type*
00174     createEntry(
00175             size_type   theBlockSize,
00176             size_type   theCount)
00177     {
00178         assert(theBlockSize >= theCount);
00179 
00180         // Push on a new entry.  The entry has no open space,
00181         // since it's greater than our block size...
00182         m_list.push_back(ListEntryType(0, VectorType::create(m_list.getMemoryManager())));
00183 
00184         // Get the new entry...
00185         ListEntryType&  theNewEntry = m_list.back();
00186 
00187         // Resize the vector to the appropriate size...
00188         assert(theNewEntry.second);
00189 
00190         theNewEntry.second->resize(theBlockSize, value_type());
00191 
00192         // Set the number of free spaces accordingly...
00193         theNewEntry.first = theBlockSize - theCount;
00194 
00195         if (theNewEntry.first != 0)
00196         {
00197             m_lastEntryFound = &theNewEntry;
00198         }
00199 
00200         // Return a pointer to the beginning of the allocated memory...
00201         return &*theNewEntry.second->begin();
00202     }
00203 
00204     ListEntryType*
00205     findEntry(size_type     theCount)
00206     {
00207         // Search for an entry that has some free space.
00208 
00209         if (m_lastEntryFound != 0 && m_lastEntryFound->first >= theCount)
00210         {
00211             return m_lastEntryFound;
00212         }
00213         else
00214         {
00215             const ListIteratorType  theEnd = m_list.end();
00216             ListIteratorType        theCurrent = m_list.begin();
00217 
00218             ListEntryType*  theEntry = 0;
00219 
00220             while(theCurrent != theEnd)
00221             {
00222                 // We're looking for the best fit, so
00223                 // if the free space and the count we're
00224                 // looking for are equal, that's pretty
00225                 // much the best we can do...
00226                 if ((*theCurrent).first == theCount)
00227                 {
00228                     theEntry = &*theCurrent;
00229 
00230                     break;
00231                 }
00232                 else if ((*theCurrent).first >= theCount)
00233                 {
00234                     // If we haven't found anything yet, the first
00235                     // entry we find that's large enough becomes
00236                     // our best fit.
00237                     //
00238                     // Otherwise, we'll assume that a smaller
00239                     // slot is a better fit, though I may be
00240                     // wrong about this...
00241                     if (theEntry == 0 ||
00242                         (*theCurrent).first < theEntry->first)
00243                     {
00244                         // Nope, so this becomes our best-fit so far.
00245                         theEntry = &*theCurrent;
00246                     }
00247 
00248                     ++theCurrent;
00249                 }
00250                 else
00251                 {
00252                     // Won't fit, so just continue...
00253                     ++theCurrent;
00254                 }
00255             }
00256 
00257             m_lastEntryFound = theEntry;
00258 
00259             return theEntry;
00260         }
00261     }
00262 
00263     // Not implemented...
00264     XalanArrayAllocator(const XalanArrayAllocator<Type>&    theSource);
00265 
00266     XalanArrayAllocator<Type>&
00267     operator=(const XalanArrayAllocator<Type>&  theSource);
00268 
00269     bool
00270     operator==(const XalanArrayAllocator<Type>& theRHS) const;
00271 
00272 
00273     // Data members...
00274     ListType            m_list;
00275 
00276     const size_type     m_blockSize;
00277 
00278     ListEntryType*      m_lastEntryFound;
00279 };
00280 
00281 
00282 
00283 XALAN_CPP_NAMESPACE_END
00284 
00285 
00286 
00287 #endif  // !defined(XALANARRAYALLOCATOR_HEADER_GUARD_1357924680)

Interpreting class diagrams

Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.

dot

Xalan-C++ XSLT Processor Version 1.10
Copyright © 1999-2004 The Apache Software Foundation. All Rights Reserved.

Apache Logo