Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.10

ReusableArenaAllocator.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #if !defined(REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680)
18 #define REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680
19 
20 
21 
22 #include <algorithm>
23 
24 
25 
26 #include "ReusableArenaBlock.hpp"
27 #include "ArenaAllocator.hpp"
28 
29 
30 
31 XALAN_CPP_NAMESPACE_BEGIN
32 
33 
34 
35 template<class ObjectType>
36 class ReusableArenaAllocator : public ArenaAllocator<ObjectType,
37  ReusableArenaBlock<ObjectType> >
38 {
39 public:
40 
42 
44 
45  typedef ArenaAllocator<ObjectType,
47 
49 
51 
56 
57 
58  /*
59  * Construct an instance that will allocate blocks of the specified size.
60  *
61  * @param theBlockSize The block size.
62  */
64  MemoryManagerType& theManager,
65  size_type theBlockSize,
66  bool destroyBlocks = false) :
67  BaseClassType(theManager, theBlockSize),
68  m_destroyBlocks(destroyBlocks)
69  {
70  }
71 
72  virtual
74  {
75  }
76 
77  /*
78  * Destroy the object, and free the block for re-use.
79  *
80  * @param theObject the address of the object.
81  * @return true if the object was deleted, false if not.
82  */
83  bool
84  destroyObject(ObjectType* theObject)
85  {
86  bool bResult = false;
87 
88  assert ( theObject != 0 );
89 
90  if ( this->m_blocks.empty() )
91  return bResult;
92 
93  iterator iTerator = this->m_blocks.begin();
94 
95  iterator iEnd = this->m_blocks.end();
96 
97  // first , run over unfull blocks ( that consentrated from the head )
98  while( iTerator != iEnd
99  && (*iTerator)->blockAvailable() )
100  {
101  if ((*iTerator)->ownsBlock(theObject) == true)
102  {
103  (*iTerator)->destroyObject(theObject);
104 
105  // move the block we have just deleted to the head of the list
106  if (iTerator != this->m_blocks.begin())
107  {
108  // move the block to the beginning
109  ReusableArenaBlockType* block = *iTerator;
110 
111  assert(block != 0);
112 
113  this->m_blocks.erase(iTerator);
114 
115  this->m_blocks.push_front(block);
116  }
117 
118  if (m_destroyBlocks)
119  {
120  destroyBlock();
121  }
122 
123  bResult = true;
124 
125  break;
126  }
127 
128  ++iTerator;
129  }
130 
131  reverse_iterator rIterator = this->m_blocks.rbegin();
132 
133  reverse_iterator rEnd = this->m_blocks.rend();
134 
135  // if the block hasn't been found from the head , start with full blocks ( from the taile)
136  while ( !bResult && rIterator != rEnd )
137  {
138  if ((*rIterator)->ownsBlock(theObject))
139  {
140  (*rIterator)->destroyObject(theObject);
141 
142  if (rIterator != this->m_blocks.rbegin())
143  {
144  // move the block to the beginning
145  ReusableArenaBlockType* block = *iTerator;
146 
147  assert(block != 0);
148 
149  this->m_blocks.erase(iTerator);
150 
151  this->m_blocks.push_front(block);
152 
153  }
154 
155  if (m_destroyBlocks)
156  {
157  destroyBlock();
158  }
159 
160  bResult = true;
161 
162  break;
163  }
164 
165  if ( *rIterator == *iTerator)
166  {
167  break;
168  }
169  else
170  {
171  ++rIterator;
172  }
173  }
174 
175  return bResult;
176 
177  assert ( bResult );
178  }
179 
180  /*
181  * Allocate a block of the appropriate size for an
182  * object. Call commitAllocation() when after
183  * the object is successfully constructed. You _must_
184  * commit an allocation before performing any other
185  * operation on the allocator.
186  *
187  *
188  * @return A pointer to a block of memory
189  */
190  virtual ObjectType*
192  {
193  if( this->m_blocks.empty()
194  || !this->m_blocks.front()->blockAvailable() )
195  {
196  this->m_blocks.push_front(
198  this->getMemoryManager(),
199  this->m_blockSize));
200 
201  assert( this->m_blocks.front() != 0 );
202  }
203 
204  assert( this->m_blocks.front() != 0 );
205  assert( this->m_blocks.front()->blockAvailable() );
206 
207  return this->m_blocks.front()->allocateBlock();
208  }
209 
210  /*
211  * Commits the allocation of the previous
212  * allocateBlock() call.
213  *
214  * @param theObject A pointer to a block of memory
215  */
216  virtual void
217  commitAllocation(ObjectType* theObject)
218  {
219  // Note that this-> is required by template lookup rules.
220  assert( this->m_blocks.empty() == false );
221  assert( this->m_blocks.front() != 0 );
222  assert( this->m_blocks.front()->ownsBlock(theObject) == true );
223 
224  this->m_blocks.front()->commitAllocation(theObject);
225 
226  if( !this->m_blocks.front()->blockAvailable() )
227  {
228  ReusableArenaBlockType* fullBlock = this->m_blocks.front();
229 
230  assert ( fullBlock != 0 );
231 
232  this->m_blocks.pop_front();
233 
234  this->m_blocks.push_back( fullBlock );
235  }
236  }
237 
238 
239  virtual bool
240  ownsObject(const ObjectType* theObject) const
241  {
242  if ( this->m_blocks.empty() )
243  return false;
244 
245  const_iterator iTerator = this->m_blocks.begin();
246 
247  const_iterator iEnd = this->m_blocks.end();
248 
249  while( iTerator != iEnd
250  && (*iTerator)->blockAvailable() )
251  {
252  if ((*iTerator)->ownsBlock(theObject) )
253  {
254  return true;
255  }
256 
257  ++iTerator;
258  }
259 
260  const_reverse_iterator rIterator = this->m_blocks.rbegin();
261 
262  const_reverse_iterator rEnd = this->m_blocks.rend();
263 
264  while( rIterator != rEnd )
265  {
266  if ((*rIterator)->ownsBlock(theObject) )
267  {
268  return true;
269  }
270 
271  if ( *iTerator == *rIterator )
272  {
273  break;
274  }
275  else
276  {
277  ++rIterator;
278  }
279  }
280 
281  return false;
282  }
283 
284 protected:
285 
286  /*
287  * The method destroys an empty block from the head of the list.
288  * For eliminating multiple create/destroy operation, the block
289  * is destroyed only if the second one is not full.
290  */
291  void
293  {
294  assert(m_destroyBlocks == true);
295 
296  if ( this->m_blocks.empty() == false)
297  {
298  const_iterator iTerator = this->m_blocks.begin();
299 
300  if ( (*iTerator)->isEmpty() )
301  {
302  ++iTerator;
303 
304  if (iTerator == this->m_blocks.end() ||
305  (*iTerator)->blockAvailable() )
306  {
307  this->m_blocks.pop_front();
308  }
309  }
310  }
311  }
312 
313  // data members
314  const bool m_destroyBlocks;
315 
316 private:
317 
318  // Not defined...
320 
322  operator=(const ReusableArenaAllocator<ObjectType>&);
323 
324  bool
325  operator==(const ReusableArenaAllocator<ObjectType>&) const;
326 };
327 
328 
329 
330 XALAN_CPP_NAMESPACE_END
331 
332 
333 
334 #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.

dot

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

Apache Logo