00001 /* 00002 * The Apache Software License, Version 1.1 00003 * 00004 * 00005 * Copyright (c) 2000 The Apache Software Foundation. All rights 00006 * reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * 1. Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in 00017 * the documentation and/or other materials provided with the 00018 * distribution. 00019 * 00020 * 3. The end-user documentation included with the redistribution, 00021 * if any, must include the following acknowledgment: 00022 * "This product includes software developed by the 00023 * Apache Software Foundation (http://www.apache.org/)." 00024 * Alternately, this acknowledgment may appear in the software itself, 00025 * if and wherever such third-party acknowledgments normally appear. 00026 * 00027 * 4. The names "Xalan" and "Apache Software Foundation" must 00028 * not be used to endorse or promote products derived from this 00029 * software without prior written permission. For written 00030 * permission, please contact apache@apache.org. 00031 * 00032 * 5. Products derived from this software may not be called "Apache", 00033 * nor may "Apache" appear in their name, without prior written 00034 * permission of the Apache Software Foundation. 00035 * 00036 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 00037 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00038 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00039 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 00040 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00041 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00042 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 00043 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00044 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00045 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00046 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00047 * SUCH DAMAGE. 00048 * ==================================================================== 00049 * 00050 * This software consists of voluntary contributions made by many 00051 * individuals on behalf of the Apache Software Foundation and was 00052 * originally based on software copyright (c) 1999, International 00053 * Business Machines, Inc., http://www.ibm.com. For more 00054 * information on the Apache Software Foundation, please see 00055 * <http://www.apache.org/>. 00056 */ 00057 00058 #if !defined(REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680) 00059 #define REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680 00060 00061 00062 00063 #include <PlatformSupport/XalanBitmap.hpp> 00064 #include <PlatformSupport/ArenaBlock.hpp> 00065 00066 00067 00068 00069 template<class ObjectType> 00070 class ReusableArenaBlock : public ArenaBlock<ObjectType> 00071 { 00072 public: 00073 00074 typedef ArenaBlock<ObjectType> BaseClassType; 00075 00076 typedef typename BaseClassType::size_type size_type; 00077 00078 /* 00079 * Construct an ArenaBlock of the specified size 00080 * of objects. 00081 * 00082 * @param theBlockSize The size of the block (the number of objects it can contain). 00083 */ 00084 ReusableArenaBlock(size_type theBlockSize) : 00085 BaseClassType(theBlockSize), 00086 m_freeList(theBlockSize), 00087 m_freeBlockCount(0) 00088 { 00089 } 00090 00091 ~ReusableArenaBlock() 00092 { 00093 // Note that this-> is required by template lookup rules. 00094 this->destroyAll(); 00095 } 00096 00097 /* 00098 * Allocate a block. Once the object is constructed, you must call 00099 * commitAllocation(). 00100 * 00101 * @return a pointer to the new block. 00102 */ 00103 virtual ObjectType* 00104 allocateBlock() 00105 { 00106 if (m_freeBlockCount == 0) 00107 { 00108 return BaseClassType::allocateBlock(); 00109 } 00110 else 00111 { 00112 return getNextFromFreeList(); 00113 } 00114 } 00115 00116 /* 00117 * Commit the previous allocation. 00118 * 00119 * @param theBlock the address that was returned by allocateBlock() 00120 */ 00121 virtual void 00122 commitAllocation(ObjectType* theBlock) 00123 { 00124 assert(theBlock != 0); 00125 assert(m_freeBlockCount == 0 || 00126 theBlock == getNextFromFreeList()); 00127 00128 if (m_freeBlockCount == 0) 00129 { 00130 BaseClassType::commitAllocation(theBlock); 00131 } 00132 else 00133 { 00134 removeFromFreeList(theBlock); 00135 } 00136 } 00137 00138 /* 00139 * Find out if there is a block available. 00140 * 00141 * @return true if one is available, false if not. 00142 */ 00143 virtual bool 00144 blockAvailable() const 00145 { 00146 return m_freeBlockCount != 0 ? true : BaseClassType::blockAvailable(); 00147 } 00148 00149 /* 00150 * Get the number of objects currently allocated in the 00151 * block. 00152 * 00153 * @return The number of objects allocated. 00154 */ 00155 virtual size_type 00156 getCountAllocated() const 00157 { 00158 return BaseClassType::getCountAllocated() - m_freeBlockCount; 00159 } 00160 00161 /* 00162 * Determine if this block owns the specified object. Note 00163 * that even if the object address is within our block, this 00164 * call will return false if no object currently occupies the 00165 * block. See also ownsBlock(). 00166 * 00167 * @param theObject the address of the object. 00168 * @return true if we own the object, false if not. 00169 */ 00170 virtual bool 00171 ownsObject(const ObjectType* theObject) const 00172 { 00173 return BaseClassType::ownsObject(theObject) && !isOnFreeList(theObject); 00174 } 00175 00176 /* 00177 * Destroy the object, and return the block to the free list. 00178 * The behavior is undefined if the object pointed to is not 00179 * owned by the block. 00180 * 00181 * @param theObject the address of the object. 00182 */ 00183 void 00184 destroyObject(ObjectType* theObject) 00185 { 00186 assert(ownsObject(theObject) == true); 00187 00188 m_destroyFunction(*theObject); 00189 00190 addToFreeList(theObject); 00191 } 00192 00193 protected: 00194 00195 /* 00196 * Determine if the block should be destroyed. Returns true, 00197 * unless the object is on the free list. The behavior is 00198 * undefined if the object pointed to is not owned by the 00199 * block. 00200 * 00201 * @param theObject the address of the object 00202 * @return true if block should be destroyed, false if not. 00203 */ 00204 virtual bool 00205 shouldDestroyBlock(const ObjectType* theObject) const 00206 { 00207 return !isOnFreeList(theObject); 00208 } 00209 00210 private: 00211 00212 // Not implemented... 00213 ReusableArenaBlock(const ReusableArenaBlock<ObjectType>&); 00214 00215 ReusableArenaBlock<ObjectType>& 00216 operator=(const ReusableArenaBlock<ObjectType>&); 00217 00218 bool 00219 operator==(const ReusableArenaBlock<ObjectType>&) const; 00220 00221 00222 /* 00223 * Determine if the block is on the free list. The behavior is 00224 * undefined if the object pointed to is not owned by the 00225 * block. 00226 * 00227 * @param theObject the address of the object 00228 * @return true if block is on the free list, false if not. 00229 */ 00230 bool 00231 isOnFreeList(const ObjectType* theObject) const 00232 { 00233 if (m_freeBlockCount == 0) 00234 { 00235 return false; 00236 } 00237 else 00238 { 00239 const size_type theOffset = 00240 getBlockOffset(theObject); 00241 00242 return m_freeList.isSet(theOffset); 00243 } 00244 } 00245 00246 /* 00247 * Add a block to the free list. The behavior is 00248 * undefined if the object pointed to is not owned by the 00249 * block. 00250 * 00251 * @param theObject the address of the object 00252 */ 00253 void 00254 addToFreeList(const ObjectType* theObject) 00255 { 00256 const size_type theOffset = 00257 getBlockOffset(theObject); 00258 00259 m_freeList.set(theOffset); 00260 00261 ++m_freeBlockCount; 00262 } 00263 00264 /* 00265 * Remove a block from the free list. The behavior is 00266 * undefined if the object pointed to is not owned by the 00267 * block. 00268 * 00269 * @param theObject the address of the object 00270 */ 00271 void 00272 removeFromFreeList(const ObjectType* theObject) 00273 { 00274 const size_type theOffset = 00275 getBlockOffset(theObject); 00276 00277 m_freeList.clear(theOffset); 00278 00279 --m_freeBlockCount; 00280 } 00281 00282 /* 00283 * Get the next block from the free list. Returns 0 if 00284 * the free list is empty. 00285 * 00286 * @return the address of the block 00287 */ 00288 ObjectType* 00289 getNextFromFreeList() 00290 { 00291 ObjectType* theResult = 0; 00292 00293 if (m_freeBlockCount > 0) 00294 { 00295 const unsigned long theFreeListSize = m_freeList.getSize(); 00296 00297 for(unsigned long i = 0; i < theFreeListSize; ++i) 00298 { 00299 if (m_freeList.isSet(i) == true) 00300 { 00301 // Note that this-> is required by template lookup rules. 00302 theResult = this->getBlockAddress(i); 00303 00304 break; 00305 } 00306 } 00307 } 00308 00309 return theResult; 00310 } 00311 00312 // Bitmap which tracks which blocks are not in use 00313 // and that should not be destroyed. 00314 XalanBitmap m_freeList; 00315 00316 // The number of blocks on the free list.) 00317 unsigned long m_freeBlockCount; 00318 }; 00319 00320 00321 00322 #endif // !defined(REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680)
Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.
![]() |
Xalan-C++ XSL Transformer Version 1.1 |
|