00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one 00003 * or more contributor license agreements. See the NOTICE file 00004 * distributed with this work for additional information 00005 * regarding copyright ownership. The ASF licenses this file 00006 * to you under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 #if !defined(XALANARRAYALLOCATOR_HEADER_GUARD_1357924680) 00019 #define XALANARRAYALLOCATOR_HEADER_GUARD_1357924680 00020 00021 00022 00023 #include <xalanc/PlatformSupport/PlatformSupportDefinitions.hpp> 00024 00025 00026 00027 #include <cassert> 00028 #include <utility> 00029 00030 00031 00032 #include <xalanc/Include/XalanVector.hpp> 00033 #include <xalanc/Include/XalanList.hpp> 00034 00035 00036 00037 XALAN_CPP_NAMESPACE_BEGIN 00038 00039 00040 00041 template<class Type> 00042 class XALAN_PLATFORMSUPPORT_EXPORT XalanArrayAllocator 00043 { 00044 public: 00045 00046 typedef XalanVector<Type> VectorType; 00047 typedef typename VectorType::size_type size_type; 00048 00049 typedef XALAN_STD_QUALIFIER pair<size_type, VectorType * > ListEntryType; 00050 typedef XalanList<ListEntryType> ListType; 00051 00052 typedef Type value_type; 00053 00054 typedef typename ListType::iterator ListIteratorType; 00055 00056 // Default size for vector allocation. 00057 enum { eDefaultBlockSize = 500 }; 00058 00059 /** 00060 * Constructor. 00061 * 00062 * @param theBlockSize The block size when allocating. 00063 */ 00064 XalanArrayAllocator(MemoryManager& theManager, 00065 size_type theBlockSize = eDefaultBlockSize) : 00066 m_list(theManager), 00067 m_blockSize(theBlockSize), 00068 m_lastEntryFound(0) 00069 { 00070 } 00071 00072 ~XalanArrayAllocator() 00073 { 00074 typename ListType::iterator iter = m_list.begin(); 00075 00076 MemoryManager& theManager = m_list.getMemoryManager(); 00077 00078 for( iter = m_list.begin(); iter != m_list.end(); ++iter) 00079 { 00080 if( (*iter).second != 0) 00081 { 00082 #if defined(XALAN_REQUIRES_QUALIFIED_DESTRUCTOR) 00083 (*iter).second->VectorType::~VectorType(); 00084 #else 00085 (*iter).second->~VectorType(); 00086 #endif 00087 theManager.deallocate((void*)(*iter).second); 00088 } 00089 } 00090 } 00091 00092 /** 00093 * Clear the instance, and release all allocated memory 00094 */ 00095 void 00096 clear() 00097 { 00098 m_list.clear(); 00099 00100 m_lastEntryFound = 0; 00101 } 00102 00103 /** 00104 * Reset the instance, but keep all memory so it can be 00105 * reused for allocations. This invalidates all previous 00106 * allocations. 00107 */ 00108 void 00109 reset() 00110 { 00111 if (m_list.empty() == true) 00112 { 00113 m_lastEntryFound = 0; 00114 } 00115 else 00116 { 00117 const ListIteratorType theEnd = m_list.end(); 00118 ListIteratorType theCurrent = m_list.begin(); 00119 00120 do 00121 { 00122 (*theCurrent).first = (*theCurrent).second->size(); 00123 00124 ++theCurrent; 00125 } while(theCurrent != theEnd); 00126 00127 m_lastEntryFound = &*m_list.begin(); 00128 } 00129 } 00130 00131 /** 00132 * Allocate slots for the given number of Types 00133 * instance and return the address of the slots. 00134 * 00135 * @param theCount The number of slots to allocate 00136 */ 00137 Type* 00138 allocate(size_type theCount) 00139 { 00140 // Handle the case of theCount being greater than the block size first... 00141 if (theCount >= m_blockSize) 00142 { 00143 return createEntry(theCount, theCount); 00144 } 00145 else 00146 { 00147 ListEntryType* theEntry = 00148 findEntry(theCount); 00149 00150 // Did we find a slot? 00151 if (theEntry == 0) 00152 { 00153 // Nope, create a new one... 00154 return createEntry(m_blockSize, theCount); 00155 } 00156 else 00157 { 00158 // The address we want is that of the first free element in the 00159 // vector... 00160 assert( theEntry->second != 0); 00161 Type* const thePointer = 00162 &*theEntry->second->begin() + (theEntry->second->size() - theEntry->first); 00163 00164 // Resize the vector to the appropriate size... 00165 theEntry->first -= theCount; 00166 00167 return thePointer; 00168 } 00169 } 00170 } 00171 00172 private: 00173 00174 // Utility functions... 00175 Type* 00176 createEntry( 00177 size_type theBlockSize, 00178 size_type theCount) 00179 { 00180 assert(theBlockSize >= theCount); 00181 00182 // Push on a new entry. The entry has no open space, 00183 // since it's greater than our block size... 00184 m_list.push_back(ListEntryType(0, VectorType::create(m_list.getMemoryManager()))); 00185 00186 // Get the new entry... 00187 ListEntryType& theNewEntry = m_list.back(); 00188 00189 // Resize the vector to the appropriate size... 00190 assert(theNewEntry.second); 00191 00192 theNewEntry.second->resize(theBlockSize, value_type()); 00193 00194 // Set the number of free spaces accordingly... 00195 theNewEntry.first = theBlockSize - theCount; 00196 00197 if (theNewEntry.first != 0) 00198 { 00199 m_lastEntryFound = &theNewEntry; 00200 } 00201 00202 // Return a pointer to the beginning of the allocated memory... 00203 return &*theNewEntry.second->begin(); 00204 } 00205 00206 ListEntryType* 00207 findEntry(size_type theCount) 00208 { 00209 // Search for an entry that has some free space. 00210 00211 if (m_lastEntryFound != 0 && m_lastEntryFound->first >= theCount) 00212 { 00213 return m_lastEntryFound; 00214 } 00215 else 00216 { 00217 const ListIteratorType theEnd = m_list.end(); 00218 ListIteratorType theCurrent = m_list.begin(); 00219 00220 ListEntryType* theEntry = 0; 00221 00222 while(theCurrent != theEnd) 00223 { 00224 // We're looking for the best fit, so 00225 // if the free space and the count we're 00226 // looking for are equal, that's pretty 00227 // much the best we can do... 00228 if ((*theCurrent).first == theCount) 00229 { 00230 theEntry = &*theCurrent; 00231 00232 break; 00233 } 00234 else if ((*theCurrent).first >= theCount) 00235 { 00236 // If we haven't found anything yet, the first 00237 // entry we find that's large enough becomes 00238 // our best fit. 00239 // 00240 // Otherwise, we'll assume that a smaller 00241 // slot is a better fit, though I may be 00242 // wrong about this... 00243 if (theEntry == 0 || 00244 (*theCurrent).first < theEntry->first) 00245 { 00246 // Nope, so this becomes our best-fit so far. 00247 theEntry = &*theCurrent; 00248 } 00249 00250 ++theCurrent; 00251 } 00252 else 00253 { 00254 // Won't fit, so just continue... 00255 ++theCurrent; 00256 } 00257 } 00258 00259 m_lastEntryFound = theEntry; 00260 00261 return theEntry; 00262 } 00263 } 00264 00265 // Not implemented... 00266 XalanArrayAllocator(const XalanArrayAllocator<Type>& theSource); 00267 00268 XalanArrayAllocator<Type>& 00269 operator=(const XalanArrayAllocator<Type>& theSource); 00270 00271 bool 00272 operator==(const XalanArrayAllocator<Type>& theRHS) const; 00273 00274 00275 // Data members... 00276 ListType m_list; 00277 00278 const size_type m_blockSize; 00279 00280 ListEntryType* m_lastEntryFound; 00281 }; 00282 00283 00284 00285 XALAN_CPP_NAMESPACE_END 00286 00287 00288 00289 #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.11 |
|