00001 /* 00002 * Copyright 1999-2004 The Apache Software Foundation. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #if !defined(ARENABLOCK_INCLUDE_GUARD_1357924680) 00018 #define ARENABLOCK_INCLUDE_GUARD_1357924680 00019 00020 00021 00022 #include <algorithm> 00023 #include <cassert> 00024 #include <set> 00025 #include <memory> 00026 00027 00028 00029 #if defined(XALAN_NO_STD_ALLOCATORS) && !defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION) 00030 #include <xalanc/PlatformSupport/XalanAllocator.hpp> 00031 #endif 00032 00033 00034 00035 XALAN_CPP_NAMESPACE_BEGIN 00036 00037 00038 00039 #if defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION) 00040 00041 template <class Type> 00042 class ArenaBlockAllocator 00043 { 00044 public: 00045 00046 typedef size_t size_type; 00047 typedef ptrdiff_t difference_type; 00048 typedef Type* pointer; 00049 typedef const Type* const_pointer; 00050 typedef Type& reference; 00051 typedef const Type& const_reference; 00052 typedef Type value_type; 00053 00054 ArenaBlockAllocator() 00055 { 00056 } 00057 00058 ArenaBlockAllocator(const ArenaBlockAllocator<Type>&) 00059 { 00060 }; 00061 00062 ~ArenaBlockAllocator() 00063 { 00064 } 00065 00066 pointer 00067 allocate( 00068 size_type size, 00069 const void* /* hint */ = 0) 00070 { 00071 return (pointer)operator new(size * sizeof(Type)); 00072 } 00073 00074 void 00075 deallocate( 00076 pointer p, 00077 size_type /* n */) 00078 { 00079 operator delete(p); 00080 } 00081 }; 00082 #endif 00083 00084 00085 00086 template<class ObjectType> 00087 class ArenaBlockDestroy 00088 { 00089 public: 00090 00091 void 00092 operator()(ObjectType& theObject) const 00093 { 00094 #if defined(XALAN_EXPLICIT_SCOPE_IN_TEMPLATE_BUG) 00095 theObject.~ObjectType(); 00096 #else 00097 theObject.ObjectType::~ObjectType(); 00098 #endif 00099 } 00100 }; 00101 00102 00103 00104 template<class ObjectType> 00105 class ArenaBlock 00106 { 00107 public: 00108 00109 #if defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION) 00110 typedef ArenaBlockAllocator<ObjectType> AllocatorType; 00111 #elif defined(XALAN_NO_STD_ALLOCATORS) 00112 typedef XalanAllocator<ObjectType> AllocatorType; 00113 #else 00114 typedef std::allocator<ObjectType> AllocatorType; 00115 #endif 00116 00117 typedef ArenaBlockDestroy<ObjectType> DestroyFunctionType; 00118 00119 typedef typename AllocatorType::size_type size_type; 00120 00121 /* 00122 * Construct an ArenaBlock of the specified size 00123 * of objects. 00124 * 00125 * @param theBlockSize The size of the block (the number of objects it can contain). 00126 */ 00127 ArenaBlock(size_type theBlockSize) : 00128 m_destroyFunction(DestroyFunctionType()), 00129 m_objectCount(0), 00130 m_blockSize(theBlockSize), 00131 m_objectBlock(0), 00132 m_allocator() 00133 { 00134 assert(theBlockSize > 0); 00135 } 00136 00137 virtual 00138 ~ArenaBlock() 00139 { 00140 destroyAll(); 00141 00142 // Release the memory... 00143 m_allocator.deallocate(m_objectBlock, m_blockSize); 00144 } 00145 00146 /* 00147 * Allocate a block. Once the object is constructed, you must call 00148 * commitAllocation(). 00149 * 00150 * @return a pointer to the new block. 00151 */ 00152 virtual ObjectType* 00153 allocateBlock() 00154 { 00155 // Any space left? 00156 if (m_objectCount == m_blockSize) 00157 { 00158 return 0; 00159 } 00160 else 00161 { 00162 // If no memory has yet been allocated, then allocate it... 00163 if (m_objectBlock == 0) 00164 { 00165 #if defined(XALAN_NEW_STD_ALLOCATOR) 00166 m_objectBlock = m_allocator.allocate(m_blockSize); 00167 #else 00168 m_objectBlock = m_allocator.allocate(m_blockSize, 0); 00169 #endif 00170 } 00171 assert(m_objectBlock != 0); 00172 00173 return m_objectBlock + m_objectCount; 00174 } 00175 } 00176 00177 /* 00178 * Commit the previous allocation. 00179 * 00180 * @param theBlock the address that was returned by allocateBlock() 00181 */ 00182 virtual void 00183 #if defined (NDEBUG) 00184 commitAllocation(ObjectType* /* theBlock */) 00185 #else 00186 commitAllocation(ObjectType* theBlock) 00187 #endif 00188 { 00189 assert(theBlock == m_objectBlock + m_objectCount); 00190 assert(m_objectCount < m_blockSize); 00191 00192 m_objectCount++; 00193 } 00194 00195 /* 00196 * Find out if there is a block available. 00197 * 00198 * @return true if one is available, false if not. 00199 */ 00200 virtual bool 00201 blockAvailable() const 00202 { 00203 return m_objectCount < m_blockSize ? true : false; 00204 } 00205 00206 /* 00207 * Get the number of objects currently allocated in the 00208 * block. 00209 * 00210 * @return The number of objects allocated. 00211 */ 00212 virtual size_type 00213 getCountAllocated() const 00214 { 00215 return m_objectCount; 00216 } 00217 00218 /* 00219 * Get the block size, that is, the number 00220 * of objects in each block. 00221 * 00222 * @return The size of the block 00223 */ 00224 size_type 00225 getBlockSize() const 00226 { 00227 return m_blockSize; 00228 } 00229 00230 /* 00231 * Determine if this block owns the specified object. Note 00232 * that even if the object address is within our block, this 00233 * call will return false if no object currently occupies the 00234 * block. See also ownsBlock(). 00235 * 00236 * @param theObject the address of the object. 00237 * @return true if we own the object, false if not. 00238 */ 00239 virtual bool 00240 ownsObject(const ObjectType* theObject) const 00241 { 00242 // Use less<>, since it's guaranteed to do pointer 00243 // comparisons correctly... 00244 XALAN_STD_QUALIFIER less<const ObjectType*> functor; 00245 00246 if (functor(theObject, m_objectBlock) == false && 00247 functor(theObject, m_objectBlock + m_objectCount) == true) 00248 { 00249 return true; 00250 } 00251 else 00252 { 00253 return false; 00254 } 00255 } 00256 00257 /* 00258 * Determine if this block owns the specified object block. 00259 * Note that, unlike ownsObject(), there does not need to 00260 * be an object at the address. 00261 * 00262 * @param theObject the address of the object 00263 * @return true if we own the object block, false if not. 00264 */ 00265 bool 00266 ownsBlock(const ObjectType* theObject) const 00267 { 00268 // Use less<>, since it's guaranteed to do pointer 00269 // comparisons correctly... 00270 XALAN_STD_QUALIFIER less<const ObjectType*> functor; 00271 00272 if (functor(theObject, m_objectBlock) == false && 00273 functor(theObject, m_objectBlock + m_blockSize) == true) 00274 { 00275 return true; 00276 } 00277 else 00278 { 00279 return false; 00280 } 00281 } 00282 00283 /* 00284 * Destroy all objects in the block. You can then reuse the 00285 * block. 00286 */ 00287 void 00288 destroyAll() 00289 { 00290 // Destroy all existing objects... 00291 XALAN_STD_QUALIFIER for_each(m_objectBlock, 00292 m_objectBlock + m_objectCount, 00293 DeleteFunctor(*this, m_destroyFunction)); 00294 00295 m_objectCount = 0; 00296 } 00297 00298 protected: 00299 00300 /* 00301 * Determine if the block should be destroyed. Called by 00302 * an instance of DeleteFunctor, this function is for 00303 * deriving classes that might want to control the destruction 00304 * of things. 00305 * 00306 * @param theObject the address of the object 00307 * @return true if block should be destroyed, false if not. 00308 */ 00309 virtual bool 00310 shouldDestroyBlock(const ObjectType* /* theObject */) const 00311 { 00312 return true; 00313 } 00314 00315 /* 00316 * Determine the offset into the block for the given address. 00317 * Behavior is undefined if the address is not within our 00318 * block 00319 * 00320 * @param theObject the address of the object 00321 * @return the offset 00322 */ 00323 size_type 00324 getBlockOffset(const ObjectType* theObject) const 00325 { 00326 assert(size_type(theObject - m_objectBlock) < m_blockSize); 00327 00328 return theObject - m_objectBlock; 00329 } 00330 00331 /* 00332 * Determine the address within our block of the object 00333 * at the specified offset. 00334 * Behavior is undefined if the offset is greater than the 00335 * block size. 00336 * 00337 * @param theObject the address of the object 00338 * @return the offset 00339 */ 00340 ObjectType* 00341 getBlockAddress(size_type theOffset) const 00342 { 00343 assert(theOffset < m_blockSize); 00344 00345 return m_objectBlock + theOffset; 00346 } 00347 00348 struct DeleteFunctor 00349 { 00350 DeleteFunctor( 00351 const ArenaBlock<ObjectType>& theArenaBlock, 00352 const DestroyFunctionType& theDestroyFunction) : 00353 m_arenaBlock(theArenaBlock), 00354 m_destroyFunction(theDestroyFunction) 00355 { 00356 } 00357 00358 void 00359 operator()(ObjectType& theObject) const 00360 { 00361 if (m_arenaBlock.shouldDestroyBlock(&theObject) == true) 00362 { 00363 m_destroyFunction(theObject); 00364 } 00365 } 00366 00367 private: 00368 00369 const ArenaBlock<ObjectType>& m_arenaBlock; 00370 const DestroyFunctionType& m_destroyFunction; 00371 }; 00372 00373 friend struct DeleteFunctor; 00374 00375 const DestroyFunctionType m_destroyFunction; 00376 00377 private: 00378 00379 // Not implemented... 00380 ArenaBlock(const ArenaBlock<ObjectType>&); 00381 00382 ArenaBlock<ObjectType>& 00383 operator=(const ArenaBlock<ObjectType>&); 00384 00385 bool 00386 operator==(const ArenaBlock<ObjectType>&) const; 00387 00388 00389 // data members... 00390 size_type m_objectCount; 00391 00392 const size_type m_blockSize; 00393 00394 ObjectType* m_objectBlock; 00395 00396 AllocatorType m_allocator; 00397 }; 00398 00399 00400 00401 XALAN_CPP_NAMESPACE_END 00402 00403 00404 00405 #endif // !defined(ARENABLOCK_INCLUDE_GUARD_1357924680)
Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.
![]() |
Xalan-C++ XSLT Processor Version 1.8 |
|