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
31namespace XALAN_CPP_NAMESPACE {
32
33
34
35template <class ObjectType,
36#if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
37 class SizeType>
38#else
39 class SizeType = unsigned short>
40#endif
41class ReusableArenaBlock : public ArenaBlockBase<ObjectType, SizeType>
42{
43
44public:
45
47
49
51
52 struct NextBlock
53 {
54 enum { VALID_OBJECT_STAMP = 0xffddffdd };
55
58
60 next(_next),
61 verificationStamp(VALID_OBJECT_STAMP)
62 {
63 }
64
65 bool
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,
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 {
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
110 }
111 }
112 }
113
114 static ThisType*
116 MemoryManager& theManager,
118 {
120
121 return XalanConstruct(
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
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
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
248protected:
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
276private:
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)
#define XALAN_CPP_NAMESPACE
Xalan-C++ namespace, including major and minor version.
BaseClassType::size_type size_type
bool shouldDestroyBlock(const ObjectType *theObject) const
ArenaBlockBase< ObjectType, SizeType > BaseClassType
ReusableArenaBlock< ObjectType, SizeType > ThisType
void destroyObject(ObjectType *theObject)
static ThisType * create(MemoryManager &theManager, size_type theBlockSize)
bool isOccupiedBlock(const ObjectType *block) const
bool ownsObject(const ObjectType *theObject) const
ReusableArenaBlock(MemoryManager &theManager, size_type theBlockSize)
size_t size_type
Definition XalanMap.hpp:46
Type * XalanConstruct(MemoryManager &theMemoryManager, Type *&theInstance)
bool operator==(const XalanVector< Type > &theLHS, const XalanVector< Type > &theRHS)
void XalanDestroy(Type &theArg)
bool isValidFor(size_type rightBorder) const