Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.11


XalanArrayAllocator.hpp
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #if !defined(XALANARRAYALLOCATOR_HEADER_GUARD_1357924680)
19 #define XALANARRAYALLOCATOR_HEADER_GUARD_1357924680
20 
21 
22 
24 
25 
26 
27 #include <cassert>
28 #include <utility>
29 
30 
31 
34 
35 
36 
37 XALAN_CPP_NAMESPACE_BEGIN
38 
39 
40 
41 template<class Type>
43 {
44 public:
45 
47  typedef typename VectorType::size_type size_type;
48 
49  typedef XALAN_STD_QUALIFIER pair<size_type, VectorType * > ListEntryType;
51 
52  typedef Type value_type;
53 
55 
56  // Default size for vector allocation.
57  enum { eDefaultBlockSize = 500 };
58 
59  /**
60  * Constructor.
61  *
62  * @param theBlockSize The block size when allocating.
63  */
64  XalanArrayAllocator(MemoryManager& theManager,
65  size_type theBlockSize = eDefaultBlockSize) :
66  m_list(theManager),
67  m_blockSize(theBlockSize),
68  m_lastEntryFound(0)
69  {
70  }
71 
73  {
74  typename ListType::iterator iter = m_list.begin();
75 
76  MemoryManager& theManager = m_list.getMemoryManager();
77 
78  for( iter = m_list.begin(); iter != m_list.end(); ++iter)
79  {
80  if( (*iter).second != 0)
81  {
82 #if defined(XALAN_REQUIRES_QUALIFIED_DESTRUCTOR)
83  (*iter).second->VectorType::~VectorType();
84 #else
85  (*iter).second->~VectorType();
86 #endif
87  theManager.deallocate((void*)(*iter).second);
88  }
89  }
90  }
91 
92  /**
93  * Clear the instance, and release all allocated memory
94  */
95  void
97  {
98  m_list.clear();
99 
100  m_lastEntryFound = 0;
101  }
102 
103  /**
104  * Reset the instance, but keep all memory so it can be
105  * reused for allocations. This invalidates all previous
106  * allocations.
107  */
108  void
110  {
111  if (m_list.empty() == true)
112  {
113  m_lastEntryFound = 0;
114  }
115  else
116  {
117  const ListIteratorType theEnd = m_list.end();
118  ListIteratorType theCurrent = m_list.begin();
119 
120  do
121  {
122  (*theCurrent).first = (*theCurrent).second->size();
123 
124  ++theCurrent;
125  } while(theCurrent != theEnd);
126 
127  m_lastEntryFound = &*m_list.begin();
128  }
129  }
130 
131  /**
132  * Allocate slots for the given number of Types
133  * instance and return the address of the slots.
134  *
135  * @param theCount The number of slots to allocate
136  */
137  Type*
138  allocate(size_type theCount)
139  {
140  // Handle the case of theCount being greater than the block size first...
141  if (theCount >= m_blockSize)
142  {
143  return createEntry(theCount, theCount);
144  }
145  else
146  {
147  ListEntryType* theEntry =
148  findEntry(theCount);
149 
150  // Did we find a slot?
151  if (theEntry == 0)
152  {
153  // Nope, create a new one...
154  return createEntry(m_blockSize, theCount);
155  }
156  else
157  {
158  // The address we want is that of the first free element in the
159  // vector...
160  assert( theEntry->second != 0);
161  Type* const thePointer =
162  &*theEntry->second->begin() + (theEntry->second->size() - theEntry->first);
163 
164  // Resize the vector to the appropriate size...
165  theEntry->first -= theCount;
166 
167  return thePointer;
168  }
169  }
170  }
171 
172 private:
173 
174  // Utility functions...
175  Type*
176  createEntry(
177  size_type theBlockSize,
178  size_type theCount)
179  {
180  assert(theBlockSize >= theCount);
181 
182  // Push on a new entry. The entry has no open space,
183  // since it's greater than our block size...
184  m_list.push_back(ListEntryType(0, VectorType::create(m_list.getMemoryManager())));
185 
186  // Get the new entry...
187  ListEntryType& theNewEntry = m_list.back();
188 
189  // Resize the vector to the appropriate size...
190  assert(theNewEntry.second);
191 
192  theNewEntry.second->resize(theBlockSize, value_type());
193 
194  // Set the number of free spaces accordingly...
195  theNewEntry.first = theBlockSize - theCount;
196 
197  if (theNewEntry.first != 0)
198  {
199  m_lastEntryFound = &theNewEntry;
200  }
201 
202  // Return a pointer to the beginning of the allocated memory...
203  return &*theNewEntry.second->begin();
204  }
205 
206  ListEntryType*
207  findEntry(size_type theCount)
208  {
209  // Search for an entry that has some free space.
210 
211  if (m_lastEntryFound != 0 && m_lastEntryFound->first >= theCount)
212  {
213  return m_lastEntryFound;
214  }
215  else
216  {
217  const ListIteratorType theEnd = m_list.end();
218  ListIteratorType theCurrent = m_list.begin();
219 
220  ListEntryType* theEntry = 0;
221 
222  while(theCurrent != theEnd)
223  {
224  // We're looking for the best fit, so
225  // if the free space and the count we're
226  // looking for are equal, that's pretty
227  // much the best we can do...
228  if ((*theCurrent).first == theCount)
229  {
230  theEntry = &*theCurrent;
231 
232  break;
233  }
234  else if ((*theCurrent).first >= theCount)
235  {
236  // If we haven't found anything yet, the first
237  // entry we find that's large enough becomes
238  // our best fit.
239  //
240  // Otherwise, we'll assume that a smaller
241  // slot is a better fit, though I may be
242  // wrong about this...
243  if (theEntry == 0 ||
244  (*theCurrent).first < theEntry->first)
245  {
246  // Nope, so this becomes our best-fit so far.
247  theEntry = &*theCurrent;
248  }
249 
250  ++theCurrent;
251  }
252  else
253  {
254  // Won't fit, so just continue...
255  ++theCurrent;
256  }
257  }
258 
259  m_lastEntryFound = theEntry;
260 
261  return theEntry;
262  }
263  }
264 
265  // Not implemented...
267 
269  operator=(const XalanArrayAllocator<Type>& theSource);
270 
271  bool
272  operator==(const XalanArrayAllocator<Type>& theRHS) const;
273 
274 
275  // Data members...
276  ListType m_list;
277 
278  const size_type m_blockSize;
279 
280  ListEntryType* m_lastEntryFound;
281 };
282 
283 
284 
285 XALAN_CPP_NAMESPACE_END
286 
287 
288 
289 #endif // !defined(XALANARRAYALLOCATOR_HEADER_GUARD_1357924680)
VectorType::size_type size_type
XalanList< ListEntryType > ListType
ListType::iterator ListIteratorType
void clear()
Clear the instance, and release all allocated memory.
XalanArrayAllocator(MemoryManager &theManager, size_type theBlockSize=eDefaultBlockSize)
Constructor.
XALAN_STD_QUALIFIER pair< size_type, VectorType *> ListEntryType
XalanVector< Type > VectorType
bool operator==(const ElemAttributeSet &theLHS, const ElemAttributeSet &theRHS)
#define XALAN_PLATFORMSUPPORT_EXPORT
void reset()
Reset the instance, but keep all memory so it can be reused for allocations.
Type * allocate(size_type theCount)
Allocate slots for the given number of Types instance and return the address of the slots...

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.11
Copyright © 1999-2012 The Apache Software Foundation.
All Rights Reserved.

Apache Logo