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)
Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.
Xalan-C++ XSLT Processor Version 1.10 |
|