Xalan-C++ API Documentation

The Xalan C++ XSLT Processor Version 1.4

Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ArenaBlock.hpp

Go to the documentation of this file.
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(ARENABLOCK_INCLUDE_GUARD_1357924680)
00059 #define ARENABLOCK_INCLUDE_GUARD_1357924680
00060 
00061 
00062 
00063 #include <algorithm>
00064 #include <cassert>
00065 #include <set>
00066 #include <memory>
00067 
00068 
00069 
00070 #if defined(XALAN_NO_STD_ALLOCATORS) && !defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION)
00071 #include <PlatformSupport/XalanAllocator.hpp>
00072 #endif
00073 
00074 
00075 
00076 #if defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION)
00077 
00078 template <class Type>
00079 class ArenaBlockAllocator
00080 {
00081 public:
00082 
00083     typedef size_t          size_type;
00084     typedef ptrdiff_t       difference_type;
00085     typedef Type*           pointer;
00086     typedef const Type*     const_pointer;
00087     typedef Type&           reference;
00088     typedef const Type&     const_reference;
00089     typedef Type            value_type;
00090 
00091     ArenaBlockAllocator()
00092     {
00093     }
00094 
00095     ArenaBlockAllocator(const ArenaBlockAllocator<Type>&)
00096     {
00097     };
00098 
00099     ~ArenaBlockAllocator()
00100     {
00101     }
00102 
00103     pointer
00104     allocate(
00105             size_type       size,
00106             const void*     /* hint */ = 0)
00107     {
00108         return (pointer)operator new(size * sizeof(Type));
00109     }
00110 
00111     void
00112     deallocate(
00113                 pointer     p,
00114                 size_type   /* n */)
00115     {
00116         operator delete(p);
00117     }
00118 };
00119 #endif
00120 
00121 
00122 
00123 template<class ObjectType>
00124 class ArenaBlockDestroy
00125 {
00126 public:
00127 
00128     void
00129     operator()(ObjectType&  theObject) const
00130     {
00131 #if defined(XALAN_EXPLICIT_SCOPE_IN_TEMPLATE_BUG)
00132         theObject.~ObjectType();
00133 #else
00134         theObject.ObjectType::~ObjectType();
00135 #endif
00136     }
00137 };
00138 
00139 
00140 
00141 template<class ObjectType>
00142 class ArenaBlock
00143 {
00144 public:
00145 
00146 #if defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION)
00147     typedef ArenaBlockAllocator<ObjectType>     AllocatorType;
00148 #elif defined(XALAN_NO_STD_ALLOCATORS)
00149     typedef XalanAllocator<ObjectType>          AllocatorType;
00150 #else
00151     typedef std::allocator<ObjectType>          AllocatorType;
00152 #endif
00153 
00154     typedef ArenaBlockDestroy<ObjectType>       DestroyFunctionType;
00155 
00156     typedef typename AllocatorType::size_type   size_type;
00157 
00158     /*
00159      * Construct an ArenaBlock of the specified size
00160      * of objects.
00161      *
00162      * @param theBlockSize The size of the block (the number of objects it can contain).
00163      */
00164     ArenaBlock(size_type    theBlockSize) :
00165         m_destroyFunction(DestroyFunctionType()),
00166         m_objectCount(0),
00167         m_blockSize(theBlockSize),
00168         m_objectBlock(0),
00169         m_allocator()
00170     {
00171         assert(theBlockSize > 0);
00172     }
00173 
00174     virtual 
00175     ~ArenaBlock()
00176     {
00177         destroyAll();
00178 
00179         // Release the memory...
00180         m_allocator.deallocate(m_objectBlock, m_blockSize);
00181     }
00182 
00183     /*
00184      * Allocate a block.  Once the object is constructed, you must call
00185      * commitAllocation().
00186      *
00187      * @return a pointer to the new block.
00188      */
00189     virtual ObjectType*
00190     allocateBlock()
00191     {
00192         // Any space left?
00193         if (m_objectCount == m_blockSize)
00194         {
00195             return 0;
00196         }
00197         else
00198         {
00199             // If no memory has yet been allocated, then allocate it...
00200             if (m_objectBlock == 0)
00201             {
00202 #if defined(XALAN_NEW_STD_ALLOCATOR)
00203                 m_objectBlock = m_allocator.allocate(m_blockSize);
00204 #else
00205                 m_objectBlock = m_allocator.allocate(m_blockSize, 0);
00206 #endif
00207             }
00208             assert(m_objectBlock != 0);
00209 
00210             return m_objectBlock + m_objectCount;
00211         }
00212     }
00213 
00214     /*
00215      * Commit the previous allocation.
00216      *
00217      * @param theBlock the address that was returned by allocateBlock()
00218      */
00219     virtual void
00220 #if defined (NDEBUG)
00221     commitAllocation(ObjectType*    /* theBlock */)
00222 #else
00223     commitAllocation(ObjectType*    theBlock)
00224 #endif
00225     {
00226         assert(theBlock == m_objectBlock + m_objectCount);
00227         assert(m_objectCount < m_blockSize);
00228 
00229         m_objectCount++;
00230     }
00231 
00232     /*
00233      * Find out if there is a block available.
00234      *
00235      * @return true if one is available, false if not.
00236      */
00237     virtual bool
00238     blockAvailable() const
00239     {
00240         return m_objectCount < m_blockSize ? true : false;
00241     }
00242 
00243     /*
00244      * Get the number of objects currently allocated in the
00245      * block.
00246      *
00247      * @return The number of objects allocated.
00248      */
00249     virtual size_type
00250     getCountAllocated() const
00251     {
00252         return m_objectCount;
00253     }
00254 
00255     /*
00256      * Get the block size, that is, the number
00257      * of objects in each block.
00258      *
00259      * @return The size of the block
00260      */
00261     size_type
00262     getBlockSize() const
00263     {
00264         return m_blockSize;
00265     }
00266 
00267     /*
00268      * Determine if this block owns the specified object.  Note
00269      * that even if the object address is within our block, this
00270      * call will return false if no object currently occupies the
00271      * block.  See also ownsBlock().
00272      *
00273      * @param theObject the address of the object.
00274      * @return true if we own the object, false if not.
00275      */
00276     virtual bool
00277     ownsObject(const ObjectType*    theObject) const
00278     {
00279 #if !defined(XALAN_NO_NAMESPACES)
00280         using std::less;
00281 #endif
00282 
00283         // Use less<>, since it's guaranteed to do pointer
00284         // comparisons correctly...
00285         less<const ObjectType*>     functor;
00286 
00287         if (functor(theObject, m_objectBlock) == false &&
00288             functor(theObject, m_objectBlock + m_objectCount) == true)
00289         {
00290             return true;
00291         }
00292         else
00293         {
00294             return false;
00295         }
00296     }
00297 
00298     /*
00299      * Determine if this block owns the specified object block.
00300      * Note that, unlike ownsObject(), there does not need to
00301      * be an object at the address.
00302      *
00303      * @param theObject the address of the object
00304      * @return true if we own the object block, false if not.
00305      */
00306     bool
00307     ownsBlock(const ObjectType*     theObject) const
00308     {
00309 #if !defined(XALAN_NO_NAMESPACES)
00310         using std::less;
00311 #endif
00312 
00313         // Use less<>, since it's guaranteed to do pointer
00314         // comparisons correctly...
00315         less<const ObjectType*>     functor;
00316 
00317         if (functor(theObject, m_objectBlock) == false &&
00318             functor(theObject, m_objectBlock + m_blockSize) == true)
00319         {
00320             return true;
00321         }
00322         else
00323         {
00324             return false;
00325         }
00326     }
00327 
00328     /*
00329      * Destroy all objects in the block.  You can then reuse the
00330      * block.
00331      */
00332     void
00333     destroyAll()
00334     {
00335 #if !defined(XALAN_NO_NAMESPACES)
00336         using std::for_each;
00337 #endif
00338 
00339         // Destroy all existing objects...
00340         for_each(m_objectBlock,
00341                  m_objectBlock + m_objectCount,
00342                  DeleteFunctor(*this, m_destroyFunction));
00343 
00344         m_objectCount = 0;
00345     }
00346 
00347 protected:
00348 
00349     /*
00350      * Determine if the block should be destroyed.  Called by
00351      * an instance of DeleteFunctor, this function is for
00352      * deriving classes that might want to control the destruction
00353      * of things.
00354      *
00355      * @param theObject the address of the object
00356      * @return true if block should be destroyed, false if not.
00357      */
00358     virtual bool
00359     shouldDestroyBlock(const ObjectType*    /* theObject */) const
00360     {
00361         return true;
00362     }
00363 
00364     /*
00365      * Determine the offset into the block for the given address.
00366      * Behavior is undefined if the address is not within our
00367      * block
00368      *
00369      * @param theObject the address of the object
00370      * @return the offset
00371      */
00372     size_type
00373     getBlockOffset(const ObjectType*    theObject) const
00374     {
00375         assert(size_type(theObject - m_objectBlock) < m_blockSize);
00376 
00377         return theObject - m_objectBlock;
00378     }
00379 
00380     /*
00381      * Determine the address within our block of the object
00382      * at the specified offset.
00383      * Behavior is undefined if the offset is greater than the
00384      * block size.
00385      *
00386      * @param theObject the address of the object
00387      * @return the offset
00388      */
00389     ObjectType*
00390     getBlockAddress(size_type   theOffset) const
00391     {
00392         assert(theOffset < m_blockSize);
00393 
00394         return m_objectBlock + theOffset;
00395     }
00396 
00397     struct DeleteFunctor
00398     {
00399         DeleteFunctor(
00400                 const ArenaBlock<ObjectType>&   theArenaBlock,
00401                 const DestroyFunctionType&      theDestroyFunction) :
00402             m_arenaBlock(theArenaBlock),
00403             m_destroyFunction(theDestroyFunction)
00404         {
00405         }
00406 
00407         void
00408         operator()(ObjectType&  theObject) const
00409         {
00410             if (m_arenaBlock.shouldDestroyBlock(&theObject) == true)
00411             {
00412                 m_destroyFunction(theObject);
00413             }
00414         }
00415 
00416     private:
00417 
00418         const ArenaBlock<ObjectType>&   m_arenaBlock;
00419         const DestroyFunctionType&      m_destroyFunction;
00420     };
00421 
00422     friend struct DeleteFunctor;
00423 
00424     const DestroyFunctionType   m_destroyFunction;
00425 
00426 private:
00427 
00428     // Not implemented...
00429     ArenaBlock(const ArenaBlock<ObjectType>&);
00430 
00431     ArenaBlock<ObjectType>&
00432     operator=(const ArenaBlock<ObjectType>&);
00433 
00434     bool
00435     operator==(const ArenaBlock<ObjectType>&) const;
00436 
00437 
00438     // data members...
00439     size_type           m_objectCount;
00440 
00441     const size_type     m_blockSize;
00442 
00443     ObjectType*         m_objectBlock;
00444 
00445     AllocatorType       m_allocator;
00446 };
00447 
00448 
00449 
00450 #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.4
Copyright © 2000, 2001, 2002 The Apache Software Foundation. All Rights Reserved.