Xalan-C++ API Reference 1.12.0
ReusableArenaAllocator.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(REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680)
20#define REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680
21
22
23
24#include <algorithm>
25
26
27
29#include "ArenaAllocator.hpp"
30
31
32
33namespace XALAN_CPP_NAMESPACE {
34
35
36
37template<class ObjectType>
38class ReusableArenaAllocator : public ArenaAllocator<ObjectType,
39 ReusableArenaBlock<ObjectType> >
40{
41public:
42
44
45 typedef typename ReusableArenaBlockType::size_type size_type;
46
47 typedef ArenaAllocator<ObjectType,
49
51
53
54 typedef typename ArenaBlockListType::iterator iterator;
55 typedef typename ArenaBlockListType::const_iterator const_iterator;
56 typedef typename ArenaBlockListType::reverse_iterator reverse_iterator;
57 typedef typename ArenaBlockListType::const_reverse_iterator const_reverse_iterator;
58
59
60 /*
61 * Construct an instance that will allocate blocks of the specified size.
62 *
63 * @param theBlockSize The block size.
64 */
66 MemoryManager& theManager,
68 bool destroyBlocks = false) :
70 m_destroyBlocks(destroyBlocks)
71 {
72 }
73
74 virtual
78
79 /*
80 * Destroy the object, and free the block for re-use.
81 *
82 * @param theObject the address of the object.
83 * @return true if the object was deleted, false if not.
84 */
85 bool
87 {
88 bool bResult = false;
89
90 assert ( theObject != 0 );
91
92 if ( this->m_blocks.empty() )
93 return bResult;
94
95 iterator iTerator = this->m_blocks.begin();
96
97 iterator iEnd = this->m_blocks.end();
98
99 // first , run over unfull blocks ( that consentrated from the head )
100 while( iTerator != iEnd
101 && (*iTerator)->blockAvailable() )
102 {
103 if ((*iTerator)->ownsBlock(theObject) == true)
104 {
105 (*iTerator)->destroyObject(theObject);
106
107 // move the block we have just deleted to the head of the list
108 if (iTerator != this->m_blocks.begin())
109 {
110 // move the block to the beginning
112
113 assert(block != 0);
114
115 this->m_blocks.erase(iTerator);
116
117 this->m_blocks.push_front(block);
118 }
119
120 if (m_destroyBlocks)
121 {
122 destroyBlock();
123 }
124
125 bResult = true;
126
127 break;
128 }
129
130 ++iTerator;
131 }
132
133 reverse_iterator rIterator = this->m_blocks.rbegin();
134
135 reverse_iterator rEnd = this->m_blocks.rend();
136
137 // if the block hasn't been found from the head , start with full blocks ( from the taile)
138 while ( !bResult && rIterator != rEnd )
139 {
140 if ((*rIterator)->ownsBlock(theObject))
141 {
142 (*rIterator)->destroyObject(theObject);
143
144 if (rIterator != this->m_blocks.rbegin())
145 {
146 // move the block to the beginning
148
149 assert(block != 0);
150
151 this->m_blocks.erase(iTerator);
152
153 this->m_blocks.push_front(block);
154
155 }
156
157 if (m_destroyBlocks)
158 {
159 destroyBlock();
160 }
161
162 bResult = true;
163
164 break;
165 }
166
167 if ( *rIterator == *iTerator)
168 {
169 break;
170 }
171 else
172 {
173 ++rIterator;
174 }
175 }
176
177 return 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(
197 ReusableArenaBlockType::create(
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
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
284protected:
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
316private:
317
318 // Not defined...
320
322 operator=(const ReusableArenaAllocator<ObjectType>&);
323
324 bool
326};
327
328
329
330}
331
332
333
334#endif // !defined(REUSABLEARENAALLOCATOR_INCLUDE_GUARD_1357924680)
#define XALAN_CPP_NAMESPACE
Xalan-C++ namespace, including major and minor version.
virtual bool ownsObject(const ObjectType *theObject) const
ReusableArenaBlock< ObjectType > ReusableArenaBlockType
ArenaAllocator< ObjectType, ReusableArenaBlockType > BaseClassType
ArenaBlockListType::const_iterator const_iterator
ArenaBlockListType::iterator iterator
ReusableArenaAllocator(MemoryManager &theManager, size_type theBlockSize, bool destroyBlocks=false)
virtual void commitAllocation(ObjectType *theObject)
ArenaBlockListType::reverse_iterator reverse_iterator
ArenaBlockListType::const_reverse_iterator const_reverse_iterator
ReusableArenaAllocator< ObjectType > ThisType
XalanList< ReusableArenaBlockType * > ArenaBlockListType
ReusableArenaBlockType::size_type size_type
bool destroyObject(ObjectType *theObject)
bool operator==(const XalanVector< Type > &theLHS, const XalanVector< Type > &theRHS)