Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.8

Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

ArenaBlock.hpp

Go to the documentation of this file.
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)

Interpreting class diagrams

Doxygen and GraphViz are used to generate this API documentation from the Xalan-C header files.

Xalan-C++ XSLT Processor Version 1.8
Copyright © 1999-2004 The Apache Software Foundation. All Rights Reserved.