Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.10

ReusableArenaBlock.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(REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680)
18 #define REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680
19 
20 
22 
23 
24 
26 
27 
28 
29 XALAN_CPP_NAMESPACE_BEGIN
30 
31 
32 
33 template <class ObjectType,
34 #if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
35  class SizeType>
36 #else
37  class SizeType = unsigned short>
38 #endif
39 class ReusableArenaBlock : public ArenaBlockBase<ObjectType, SizeType>
40 {
41 
42 public:
43 
45 
47 
49 
50  struct NextBlock
51  {
52  enum { VALID_OBJECT_STAMP = 0xffddffdd };
53 
55  const int verificationStamp;
56 
58  next(_next),
60  {
61  }
62 
63  bool
64  isValidFor( size_type rightBorder ) const
65  {
66  return ( ( verificationStamp == int(VALID_OBJECT_STAMP)) &&
67  ( next <= rightBorder ) ) ? true : false ;
68  }
69 
70  static NextBlock*
71  cast(void* thePointer)
72  {
73  return reinterpret_cast<NextBlock*>(thePointer);
74  }
75 
76  static const NextBlock*
77  cast(const void* thePointer)
78  {
79  return reinterpret_cast<const NextBlock*>(thePointer);
80  }
81  };
82 
83  /*
84  * Construct an ArenaBlock of the specified size
85  * of objects.
86  *
87  * @param theBlockSize The size of the block (the
88  * number of objects it can contain).
89  */
91  MemoryManagerType& theManager,
92  size_type theBlockSize) :
93  BaseClassType(theManager, theBlockSize),
94  m_firstFreeBlock(0),
95  m_nextFreeBlock(0)
96 
97  {
98  XALAN_STATIC_ASSERT(sizeof(ObjectType) >= sizeof(NextBlock));
99 
100  for( size_type i = 0; i < this->m_blockSize; ++i )
101  {
102  new (&this->m_objectBlock[i]) NextBlock(size_type(i + 1));
103  }
104  }
105 
107  {
108  size_type removedObjects = 0;
109 
110  for (size_type i = 0;
111  i < this->m_blockSize &&
112  removedObjects < this->m_objectCount;
113  ++i)
114  {
115  NextBlock* const pStruct =
116  NextBlock::cast(&this->m_objectBlock[i]);
117 
118  if ( isOccupiedBlock(pStruct) )
119  {
120  this->m_objectBlock[i].~ObjectType();
121 
122  ++removedObjects;
123  }
124  }
125  }
126 
127  static ThisType*
129  MemoryManagerType& theManager,
130  size_type theBlockSize)
131  {
132  ThisType* theInstance;
133 
134  return XalanConstruct(
135  theManager,
136  theInstance,
137  theManager,
138  theBlockSize);
139  }
140 
141  /*
142  * Allocate a block. Once the object is constructed, you must call
143  * commitAllocation().
144  *
145  * @return a pointer to the new block.
146  */
147  ObjectType*
149  {
150  if ( this->m_objectCount == this->m_blockSize )
151  {
152  assert ( this->m_firstFreeBlock == (this->m_blockSize + 1) );
153 
154  return 0;
155  }
156  else
157  {
158  assert( this->m_objectCount < this->m_blockSize );
159 
160  ObjectType* theResult = 0;
161 
162  assert ( this->m_firstFreeBlock <= this->m_blockSize );
163  assert ( this->m_nextFreeBlock <= this->m_blockSize );
164 
165  // check if any part was allocated but not commited
166  if(this->m_firstFreeBlock != this->m_nextFreeBlock)
167  {
168  // return the previously allocated block and wait for a commit
169  theResult = this->m_objectBlock + this->m_firstFreeBlock;
170  }
171  else
172  {
173  theResult = this->m_objectBlock + this->m_firstFreeBlock;
174 
175  assert(size_type(theResult - this->m_objectBlock) < this->m_blockSize);
176 
177  this->m_nextFreeBlock = NextBlock::cast(theResult)->next;
178 
179  assert(NextBlock::cast(theResult)->isValidFor(this->m_blockSize));
180  assert(this->m_nextFreeBlock <= this->m_blockSize);
181 
182  ++this->m_objectCount;
183  }
184 
185  return theResult;
186  }
187  }
188 
189  /*
190  * Commit the previous allocation.
191  *
192  * @param theBlock the address that was returned by allocateBlock()
193  */
194  void
195  commitAllocation(ObjectType* /* theBlock */)
196  {
197  assert ( this->m_objectCount <= this->m_blockSize );
198 
199  this->m_firstFreeBlock = this->m_nextFreeBlock;
200  }
201 
202  /*
203  * Destroy the object, and return the block to the free list.
204  * The behavior is undefined if the object pointed to is not
205  * owned by the block.
206  *
207  * @param theObject the address of the object.
208  */
209  void
210  destroyObject(ObjectType* theObject)
211  {
212  assert(theObject != 0);
213 
214  // check if any uncommited block is there, add it to the list
215  if ( this->m_firstFreeBlock != this->m_nextFreeBlock )
216  {
217  // Return it to the pool of free blocks
218  void* const p = this->m_objectBlock + this->m_firstFreeBlock;
219 
220  new (p) NextBlock(this->m_nextFreeBlock);
221 
222  this->m_nextFreeBlock = this->m_firstFreeBlock;
223  }
224 
225  assert(ownsObject(theObject) == true);
226  assert(shouldDestroyBlock(theObject));
227 
228  XalanDestroy(*theObject);
229 
230  new (theObject) NextBlock(this->m_firstFreeBlock);
231 
232  m_firstFreeBlock =
233  this->m_nextFreeBlock =
234  size_type(theObject - this->m_objectBlock);
235 
236  assert (this->m_firstFreeBlock <= this->m_blockSize);
237 
238  --this->m_objectCount;
239  }
240 
241  /*
242  * Determine if this block owns the specified object. Note
243  * that even if the object address is within our block, this
244  * call will return false if no object currently occupies the
245  * block. See also ownsBlock().
246  *
247  * @param theObject the address of the object.
248  * @return true if we own the object, false if not.
249  */
250  bool
251  ownsObject(const ObjectType* theObject) const
252  {
253  assert ( theObject != 0 );
254 
255  return isOccupiedBlock(NextBlock::cast(theObject));
256  }
257 
258 protected:
259 
260  /*
261  * Determine if the block should be destroyed. Returns true,
262  * unless the object is on the free list. The behavior is
263  * undefined if the object pointed to is not owned by the
264  * block.
265  *
266  * @param theObject the address of the object
267  * @return true if block should be destroyed, false if not.
268  */
269  bool
270  shouldDestroyBlock(const ObjectType* theObject) const
271  {
272  assert(size_type(theObject - this->m_objectBlock) < this->m_blockSize);
273 
274  return !isOnFreeList(theObject);
275  }
276 
277  bool
278  isOccupiedBlock(const NextBlock* block) const
279  {
280  assert( block !=0 );
281 
282  return !(this->ownsBlock(reinterpret_cast<const ObjectType*>(block)) &&
283  block->isValidFor(this->m_blockSize));
284  }
285 
286 private:
287 
288  // Not implemented...
290 
293 
294  bool
295  operator==(const ReusableArenaBlock<ObjectType, SizeType>&) const;
296 
297 
298  /*
299  * Determine if the block is on the free list. The behavior is
300  * undefined if the object pointed to is not owned by the
301  * block.
302  *
303  * @param theObject the address of the object
304  * @return true if block is on the free list, false if not.
305  */
306  bool
307  isOnFreeList(const ObjectType* theObject) const
308  {
309  if ( this->m_objectCount == 0 )
310  {
311  return false;
312  }
313  else
314  {
315  ObjectType* pRunPtr = this->m_objectBlock + this->m_firstFreeBlock;
316 
317  for (size_type i = 0;
318  i < this->m_blockSize - this->m_objectCount;
319  ++i)
320  {
321  assert(this->ownsBlock(pRunPtr));
322 
323  if (pRunPtr == theObject)
324  {
325  return true;
326  }
327  else
328  {
329  NextBlock* const p = reinterpret_cast<NextBlock*>(pRunPtr);
330 
331  assert(p->isValidFor(this->m_blockSize));
332 
333  pRunPtr = this->m_objectBlock + p->next;
334  }
335  }
336 
337  return false;
338  }
339  }
340 
341  // Data members...
342  size_type m_firstFreeBlock;
343 
344  size_type m_nextFreeBlock;
345 };
346 
347 
348 
349 XALAN_CPP_NAMESPACE_END
350 
351 
352 
353 #endif // !defined(REUSABLEARENABLOCK_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