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