dmitryh     2004/07/05 07:53:51

  Modified:    c/src/xalanc/PlatformSupport ArenaAllocator.hpp
                        ArenaBlock.hpp ReusableArenaAllocator.hpp
                        ReusableArenaBlock.hpp
  Log:
  Improvements of the Xalan memory management (experimental).
      Submitted by:                               Dmitry Hayes
      Reviewed by:                                Matthew Hoyt
  
  Revision  Changes    Path
  1.5       +4 -4      xml-xalan/c/src/xalanc/PlatformSupport/ArenaAllocator.hpp
  
  Index: ArenaAllocator.hpp
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/c/src/xalanc/PlatformSupport/ArenaAllocator.hpp,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ArenaAllocator.hpp        26 Feb 2004 22:34:18 -0000      1.4
  +++ ArenaAllocator.hpp        5 Jul 2004 14:53:51 -0000       1.5
  @@ -20,7 +20,7 @@
   
   
   #include <algorithm>
  -#include <vector>
  +#include <list>
   
   
   
  @@ -112,7 +112,7 @@
        size_type
        getBlockCount() const
        {
  -             return m_blocks.size();
  +             return (size_type)m_blocks.size();
        }
   
        /*
  @@ -196,9 +196,9 @@
   
        // data members...
   #if defined(XALAN_NO_STD_NAMESPACE)
  -     typedef vector<ArenaBlockType*>                 ArenaBlockListType;
  +     typedef list<ArenaBlockType*>                   ArenaBlockListType;
   #else
  -     typedef std::vector<ArenaBlockType*>    ArenaBlockListType;
  +     typedef std::list<ArenaBlockType*>      ArenaBlockListType;
   #endif
   
        size_type                       m_blockSize;
  
  
  
  1.5       +24 -290   xml-xalan/c/src/xalanc/PlatformSupport/ArenaBlock.hpp
  
  Index: ArenaBlock.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/src/xalanc/PlatformSupport/ArenaBlock.hpp,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ArenaBlock.hpp    26 Feb 2004 22:34:18 -0000      1.4
  +++ ArenaBlock.hpp    5 Jul 2004 14:53:51 -0000       1.5
  @@ -18,105 +18,26 @@
   #define ARENABLOCK_INCLUDE_GUARD_1357924680
   
   
  -
  -#include <algorithm>
  -#include <cassert>
  -#include <set>
  -#include <memory>
  -
  -
  -
  -#if defined(XALAN_NO_STD_ALLOCATORS) && 
!defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION)
  -#include <xalanc/PlatformSupport/XalanAllocator.hpp>
  -#endif
  +#include <xalanc/PlatformSupport/ArenaBlockBase.hpp>
   
   
   
   XALAN_CPP_NAMESPACE_BEGIN
   
   
  -
  -#if defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION)
  -
  -template <class Type>
  -class ArenaBlockAllocator
  -{
  -public:
  -
  -     typedef size_t                  size_type;
  -     typedef ptrdiff_t               difference_type;
  -     typedef Type*                   pointer;
  -     typedef const Type*             const_pointer;
  -     typedef Type&                   reference;
  -     typedef const Type&             const_reference;
  -     typedef Type                    value_type;
  -
  -     ArenaBlockAllocator()
  -     {
  -     }
  -
  -     ArenaBlockAllocator(const ArenaBlockAllocator<Type>&)
  -     {
  -     };
  -
  -     ~ArenaBlockAllocator()
  -     {
  -     }
  -
  -     pointer
  -     allocate(
  -                     size_type               size,
  -                     const void*             /* hint */ = 0)
  -     {
  -             return (pointer)operator new(size * sizeof(Type));
  -     }
  -
  -     void
  -     deallocate(
  -                             pointer         p,
  -                             size_type       /* n */)
  -     {
  -             operator delete(p);
  -     }
  -};
  -#endif
  -
  -
  -
  -template<class ObjectType>
  -class ArenaBlockDestroy
  -{
  -public:
  -
  -     void
  -     operator()(ObjectType&  theObject) const
  -     {
  -#if defined(XALAN_EXPLICIT_SCOPE_IN_TEMPLATE_BUG)
  -             theObject.~ObjectType();
  +template<class ObjectType,
  +#if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
  +              class size_Type>
   #else
  -             theObject.ObjectType::~ObjectType();
  +              class size_Type  = size_t >
   #endif
  -     }
  -};
  -
  -
  -
  -template<class ObjectType>
  -class ArenaBlock
  +class ArenaBlock : public ArenaBlockBase<ObjectType,size_Type>
   {
   public:
  +     typedef ArenaBlockBase<ObjectType,size_Type>            BaseClassType;
  +     
  +     typedef typename BaseClassType::size_type               size_type;
   
  -#if defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION)
  -     typedef ArenaBlockAllocator<ObjectType>         AllocatorType;
  -#elif defined(XALAN_NO_STD_ALLOCATORS)
  -     typedef XalanAllocator<ObjectType>                      AllocatorType;
  -#else
  -     typedef std::allocator<ObjectType>                      AllocatorType;
  -#endif
  -
  -     typedef ArenaBlockDestroy<ObjectType>           DestroyFunctionType;
  -
  -     typedef typename AllocatorType::size_type       size_type;
   
        /*
         * Construct an ArenaBlock of the specified size
  @@ -124,23 +45,22 @@
         *
         * @param theBlockSize The size of the block (the number of objects it 
can contain).
         */
  -     ArenaBlock(size_type    theBlockSize) :
  -             m_destroyFunction(DestroyFunctionType()),
  -             m_objectCount(0),
  -             m_blockSize(theBlockSize),
  -             m_objectBlock(0),
  -             m_allocator()
  +     ArenaBlock(size_type    theBlockSize) : 
  +     BaseClassType(theBlockSize)
        {
  -             assert(theBlockSize > 0);
        }
   
  -     virtual 
  +      
        ~ArenaBlock()
  -     {
  -             destroyAll();
  +     {       
  +             assert( m_objectCount <= m_blockSize );
  +
  +             
  +             for ( size_type i = 0; i < m_objectCount  ; ++i )
  +             {
  +                     m_objectBlock[i].~ObjectType();
  +             }
   
  -             // Release the memory...
  -             m_allocator.deallocate(m_objectBlock, m_blockSize);
        }
   
        /*
  @@ -149,7 +69,7 @@
         *
         * @return a pointer to the new block.
         */
  -     virtual ObjectType*
  +     ObjectType*
        allocateBlock()
        {
                // Any space left?
  @@ -159,15 +79,6 @@
                }
                else
                {
  -                     // If no memory has yet been allocated, then allocate 
it...
  -                     if (m_objectBlock == 0)
  -                     {
  -#if defined(XALAN_NEW_STD_ALLOCATOR)
  -                             m_objectBlock = 
m_allocator.allocate(m_blockSize);
  -#else
  -                             m_objectBlock = 
m_allocator.allocate(m_blockSize, 0);
  -#endif
  -                     }
                        assert(m_objectBlock != 0);
   
                        return m_objectBlock + m_objectCount;
  @@ -179,7 +90,7 @@
         *
         * @param theBlock the address that was returned by allocateBlock()
         */
  -     virtual void
  +     void
   #if defined (NDEBUG)
        commitAllocation(ObjectType*    /* theBlock */)
   #else
  @@ -193,41 +104,6 @@
        }
   
        /*
  -      * Find out if there is a block available.
  -      *
  -      * @return true if one is available, false if not.
  -      */
  -     virtual bool
  -     blockAvailable() const
  -     {
  -             return m_objectCount < m_blockSize ? true : false;
  -     }
  -
  -     /*
  -      * Get the number of objects currently allocated in the
  -      * block.
  -      *
  -      * @return The number of objects allocated.
  -      */
  -     virtual size_type
  -     getCountAllocated() const
  -     {
  -             return m_objectCount;
  -     }
  -
  -     /*
  -      * Get the block size, that is, the number
  -      * of objects in each block.
  -      *
  -      * @return The size of the block
  -      */
  -     size_type
  -     getBlockSize() const
  -     {
  -             return m_blockSize;
  -     }
  -
  -     /*
         * Determine if this block owns the specified object.  Note
         * that even if the object address is within our block, this
         * call will return false if no object currently occupies the
  @@ -236,144 +112,11 @@
         * @param theObject the address of the object.
         * @return true if we own the object, false if not.
         */
  -     virtual bool
  -     ownsObject(const ObjectType*    theObject) const
  -     {
  -             // Use less<>, since it's guaranteed to do pointer
  -             // comparisons correctly...
  -             XALAN_STD_QUALIFIER less<const ObjectType*>             functor;
  -
  -             if (functor(theObject, m_objectBlock) == false &&
  -                     functor(theObject, m_objectBlock + m_objectCount) == 
true)
  -             {
  -                     return true;
  -             }
  -             else
  -             {
  -                     return false;
  -             }
  -     }
  -
  -     /*
  -      * Determine if this block owns the specified object block.
  -      * Note that, unlike ownsObject(), there does not need to
  -      * be an object at the address.
  -      *
  -      * @param theObject the address of the object
  -      * @return true if we own the object block, false if not.
  -      */
        bool
  -     ownsBlock(const ObjectType*             theObject) const
  -     {
  -             // Use less<>, since it's guaranteed to do pointer
  -             // comparisons correctly...
  -             XALAN_STD_QUALIFIER less<const ObjectType*>             functor;
  -
  -             if (functor(theObject, m_objectBlock) == false &&
  -                     functor(theObject, m_objectBlock + m_blockSize) == true)
  -             {
  -                     return true;
  -             }
  -             else
  -             {
  -                     return false;
  -             }
  -     }
  -
  -     /*
  -      * Destroy all objects in the block.  You can then reuse the
  -      * block.
  -      */
  -     void
  -     destroyAll()
  -     {
  -             // Destroy all existing objects...
  -             XALAN_STD_QUALIFIER for_each(m_objectBlock,
  -                              m_objectBlock + m_objectCount,
  -                              DeleteFunctor(*this, m_destroyFunction));
  -
  -             m_objectCount = 0;
  -     }
  -
  -protected:
  -
  -     /*
  -      * Determine if the block should be destroyed.  Called by
  -      * an instance of DeleteFunctor, this function is for
  -      * deriving classes that might want to control the destruction
  -      * of things.
  -      *
  -      * @param theObject the address of the object
  -      * @return true if block should be destroyed, false if not.
  -      */
  -     virtual bool
  -     shouldDestroyBlock(const ObjectType*    /* theObject */) const
  -     {
  -             return true;
  -     }
  -
  -     /*
  -      * Determine the offset into the block for the given address.
  -      * Behavior is undefined if the address is not within our
  -      * block
  -      *
  -      * @param theObject the address of the object
  -      * @return the offset
  -      */
  -     size_type
  -     getBlockOffset(const ObjectType*        theObject) const
  -     {
  -             assert(size_type(theObject - m_objectBlock) < m_blockSize);
  -
  -             return theObject - m_objectBlock;
  -     }
  -
  -     /*
  -      * Determine the address within our block of the object
  -      * at the specified offset.
  -      * Behavior is undefined if the offset is greater than the
  -      * block size.
  -      *
  -      * @param theObject the address of the object
  -      * @return the offset
  -      */
  -     ObjectType*
  -     getBlockAddress(size_type       theOffset) const
  +     ownsObject(const ObjectType*    theObject) const
        {
  -             assert(theOffset < m_blockSize);
  -
  -             return m_objectBlock + theOffset;
  +             return isInBorders(theObject, m_objectCount);
        }
  -
  -     struct DeleteFunctor
  -     {
  -             DeleteFunctor(
  -                             const ArenaBlock<ObjectType>&   theArenaBlock,
  -                             const DestroyFunctionType&              
theDestroyFunction) :
  -                     m_arenaBlock(theArenaBlock),
  -                     m_destroyFunction(theDestroyFunction)
  -             {
  -             }
  -
  -             void
  -             operator()(ObjectType&  theObject) const
  -             {
  -                     if (m_arenaBlock.shouldDestroyBlock(&theObject) == true)
  -                     {
  -                             m_destroyFunction(theObject);
  -                     }
  -             }
  -
  -     private:
  -
  -             const ArenaBlock<ObjectType>&   m_arenaBlock;
  -             const DestroyFunctionType&              m_destroyFunction;
  -     };
  -
  -     friend struct DeleteFunctor;
  -
  -     const DestroyFunctionType       m_destroyFunction;
  -
   private:
   
        // Not implemented...
  @@ -385,15 +128,6 @@
        bool
        operator==(const ArenaBlock<ObjectType>&) const;
   
  -
  -     // data members...
  -     size_type                       m_objectCount;
  -
  -     const size_type         m_blockSize;
  -
  -     ObjectType*                     m_objectBlock;
  -
  -     AllocatorType           m_allocator;
   };
   
   
  
  
  
  1.5       +184 -78   
xml-xalan/c/src/xalanc/PlatformSupport/ReusableArenaAllocator.hpp
  
  Index: ReusableArenaAllocator.hpp
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/c/src/xalanc/PlatformSupport/ReusableArenaAllocator.hpp,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ReusableArenaAllocator.hpp        26 Feb 2004 22:34:18 -0000      1.4
  +++ ReusableArenaAllocator.hpp        5 Jul 2004 14:53:51 -0000       1.5
  @@ -20,7 +20,7 @@
   
   
   #include <algorithm>
  -#include <vector>
  +#include <list>
   
   
   
  @@ -47,19 +47,26 @@
                                                   ReusableArenaBlockType>      
        BaseClassType;
   
   #if defined (XALAN_NO_STD_NAMESPACE)
  -     typedef vector<ReusableArenaBlockType*>                         
ArenaBlockListType;
  +     typedef list<ReusableArenaBlockType*>                           
ArenaBlockListType;
  +
   #else
  -     typedef std::vector<ReusableArenaBlockType*>            
ArenaBlockListType;
  +     typedef std::list<ReusableArenaBlockType*>                      
ArenaBlockListType;
   #endif
   
  +     typedef typename ArenaBlockListType::iterator                           
iterator;
  +     typedef typename ArenaBlockListType::const_iterator                     
const_iterator;
  +     typedef typename ArenaBlockListType::reverse_iterator           
reverse_iterator;
  +     typedef typename ArenaBlockListType::const_reverse_iterator  
const_reverse_iterator;
  +
  +
        /*
         * Construct an instance that will allocate blocks of the specified 
size.
         *
         * @param theBlockSize The block size.
         */
  -     ReusableArenaAllocator(size_type        theBlockSize) :
  +     ReusableArenaAllocator(size_type        theBlockSize, bool 
destroyBlocks = false) :
                BaseClassType(theBlockSize),
  -             m_lastBlockReferenced(0)
  +             m_destroyBlocks(destroyBlocks)
        {
        }
   
  @@ -77,42 +84,98 @@
        bool
        destroyObject(ObjectType*       theObject)
        {
  -             bool    fSuccess = false;
  +             bool bResult = false;
  +
  +             assert ( theObject != 0 );
  +
  +             if ( this->m_blocks.empty() )
  +                     return bResult;
  +
  +             iterator iTerator = this->m_blocks.begin();
   
  -             // Check this, just in case...
  -             if (m_lastBlockReferenced != 0 && 
m_lastBlockReferenced->ownsObject(theObject) == true)
  +             iterator iEnd = this->m_blocks.end();
  +
  +             // first , run over unfull blocks ( that consentrated from the 
head )
  +             while( iTerator != iEnd 
  +                                     && (*iTerator)->blockAvailable() )
                {
  -                     m_lastBlockReferenced->destroyObject(theObject);
  +                     if ((*iTerator)->ownsBlock(theObject) == true)
  +                     {
  +                             (*iTerator)->destroyObject(theObject);
  +                             
  +                             // move the block we have just deleted to the 
head of the list
  +                             if (iTerator != this->m_blocks.begin())
  +                             {
  +                                     // move the block to the beginning
  +                                     ReusableArenaBlockType* block = 
*iTerator;
  +
  +                                     assert(block != 0);
  +                                     
  +                                     this->m_blocks.erase(iTerator);
  +
  +                                     this->m_blocks.push_front(block);
  +                             }
  +
  +                             if (m_destroyBlocks)
  +                             {
  +                                     destroyBlock();
  +                             }
  +
  +                             bResult = true;
   
  -                     fSuccess = true;
  +                             break;
  +                     }
  +
  +                     ++iTerator;
                }
  -             else
  -             {
  -                     // Note that this-> is required by template lookup 
rules.
  -                     const typename ArenaBlockListType::reverse_iterator     
theEnd = this->m_blocks.rend();
   
  -                     typename ArenaBlockListType::reverse_iterator   i = 
this->m_blocks.rbegin();
  +             reverse_iterator rIterator = this->m_blocks.rbegin();
  +
  +             reverse_iterator rEnd = this->m_blocks.rend();
   
  -                     while(i != theEnd)
  +             // if the block hasn't been found from the head , start with 
full blocks ( from the taile)
  +             while ( !bResult && rIterator != rEnd )
  +             {
  +                     if ((*rIterator)->ownsBlock(theObject))
                        {
  -                             if ((*i)->ownsObject(theObject) == true)
  +                             (*rIterator)->destroyObject(theObject);
  +
  +                             if (rIterator != this->m_blocks.rbegin())
                                {
  -                                     m_lastBlockReferenced = *i;
  +                                     // move the block to the beginning
  +                                     ReusableArenaBlockType* block = 
*iTerator;
   
  -                                     
m_lastBlockReferenced->destroyObject(theObject);
  +                                     assert(block != 0);
  +                                     
  +                                     this->m_blocks.erase(iTerator);
   
  -                                     fSuccess = true;
  +                                     this->m_blocks.push_front(block);
   
  -                                     break;
                                }
  -                             else
  +
  +                             if (m_destroyBlocks)
                                {
  -                                     ++i;
  +                                     destroyBlock();
                                }
  +
  +                             bResult = true;
  +
  +                             break; 
  +                     }
  +
  +                     if ( *rIterator == *iTerator)
  +                     {
  +                             break;
  +                     }
  +                     else
  +                     {
  +                             ++rIterator;
                        }
                }
   
  -             return fSuccess;
  +             return bResult;
  +
  +             assert ( bResult );
        }
   
        /*
  @@ -121,51 +184,27 @@
         * the object is successfully constructed.  You _must_
         * commit an allocation before performing any other
         * operation on the allocator.
  +      * 
         *
         * @return A pointer to a block of memory
         */
        virtual ObjectType*
        allocateBlock()
        {
  -             if (m_lastBlockReferenced == 0 ||
  -                     m_lastBlockReferenced->blockAvailable() == false)
  +
  +             if( this->m_blocks.empty() 
  +                     || !this->m_blocks.front()->blockAvailable() )
                {
  -                     // Search back for a block with some space available... 
        
  -                     const typename ArenaBlockListType::reverse_iterator     
theEnd = this->m_blocks.rend();
  +                     this->m_blocks.push_front(new 
ReusableArenaBlockType(this->m_blockSize));
                        
  -                     // Note that this-> is required by template lookup 
rules.
  -                     typename ArenaBlockListType::reverse_iterator   i = 
this->m_blocks.rbegin();
  -
  -                     while(i != theEnd)
  -                     {
  -                             assert(*i != 0);
  +                     assert( this->m_blocks.front() != 0 );
  +             }
   
  -                             if (*i != m_lastBlockReferenced && 
(*i)->blockAvailable() == true)
  -                             {
  -                                     // Ahh, found one with free space.
  -                                     m_lastBlockReferenced = *i;
  +             assert( this->m_blocks.front() != 0 );
  +             assert( this->m_blocks.front()->blockAvailable() );
   
  -                                     break;
  -                             }
  -                             else
  -                             {
  -                                     ++i;
  -                             }
  -                     }
  -
  -                     if (i == theEnd)
  -                     {
  -                             // No blocks have free space available, so 
create a new block, and
  -                             // push it on the list.
  -                             // Note that this-> is required by template 
lookup rules.
  -                             m_lastBlockReferenced = new 
ReusableArenaBlockType(this->m_blockSize);
  +             return this->m_blocks.front()->allocateBlock();
   
  -                             this->m_blocks.push_back(m_lastBlockReferenced);
  -                     }
  -             }
  -             assert(m_lastBlockReferenced != 0 && 
m_lastBlockReferenced->blockAvailable() == true);
  -
  -             return m_lastBlockReferenced->allocateBlock();
        }
   
        /*
  @@ -178,40 +217,109 @@
        commitAllocation(ObjectType*    theObject)
        {
                // Note that this-> is required by template lookup rules.
  -             assert(this->m_blocks.empty() == false && m_lastBlockReferenced 
!= 0 && m_lastBlockReferenced->ownsBlock(theObject) == true);
  +             assert( this->m_blocks.empty() == false );
  +             assert( this->m_blocks.front() != 0 );
  +             assert( this->m_blocks.front()->ownsBlock(theObject) == true );
   
  -             m_lastBlockReferenced->commitAllocation(theObject);
  -             assert(m_lastBlockReferenced->ownsObject(theObject) == true);
  -     }
  +             this->m_blocks.front()->commitAllocation(theObject);
   
  -     virtual void
  -     reset()
  -     {
  -             m_lastBlockReferenced = 0;
  +             if( !this->m_blocks.front()->blockAvailable() )
  +             {
  +                     ReusableArenaBlockType* fullBlock = 
this->m_blocks.front();
  +
  +                     assert ( fullBlock != 0 );
   
  -             BaseClassType::reset();
  +                     this->m_blocks.pop_front();
  +
  +                     this->m_blocks.push_back( fullBlock );
  +             }
        }
   
  +
        virtual bool
        ownsObject(const ObjectType*    theObject) const
        {
  -             bool    fResult = false;
  +             if ( this->m_blocks.empty() )
  +                     return false;
  +
  +             const_iterator iTerator = this->m_blocks.begin();
  +
  +             const_iterator iEnd = this->m_blocks.end();
   
  -             // If no block has ever been referenced, then we haven't 
allocated
  -             // any objects.
  -             if (m_lastBlockReferenced != 0)
  +             while( iTerator != iEnd 
  +                                     && (*iTerator)->blockAvailable() )
                {
  -                     // Check the last referenced block first.
  -                     fResult = m_lastBlockReferenced->ownsObject(theObject);
  +                     if ((*iTerator)->ownsBlock(theObject) )
  +                     {
  +                             return true;
  +                     }
  +
  +                     ++iTerator;
  +             }
  +
  +             const_reverse_iterator rIterator = this->m_blocks.rbegin();
  +
  +             const_reverse_iterator rEnd = this->m_blocks.rend();
   
  -                     if (fResult == false)
  +             while( rIterator != rEnd )
  +             {
  +                     if ((*rIterator)->ownsBlock(theObject) )
                        {
  -                             fResult = BaseClassType::ownsObject(theObject);
  +                             return true;
  +                     }
  +
  +                     if ( *iTerator == *rIterator )
  +                     {
  +                             break;
  +                     }
  +                     else
  +                     {
  +                             ++rIterator;
                        }
                }
   
  -             return fResult;
  +             return false;
        }
  +protected:
  +     /*
  +      * The method destroys an empty block from the head of the list.
  +      * For eleminating multiple create/destroy operation , the block is 
destroyed 
  +      * only if the second one is not full
  +      *
  +      * @return  true if destroyed , fasle elsewhere
  +      */
  +     bool
  +     destroyBlock()
  +     {
  +             bool bResult = false;
  +
  +             if ( this->m_blocks.empty() )
  +             {
  +                     return bResult;
  +             }
  +
  +             const_iterator iTerator = this->m_blocks.begin();
  +
  +             if ( (*iTerator)->isEmpty() )
  +             {
  +                     ++iTerator;
  +
  +                     if (iTerator == this->m_blocks.end() ||
  +                             (*iTerator)->blockAvailable() )
  +                     {
  +                             this->m_blocks.pop_front();
  +                             
  +                             bResult = true;
  +                     }
  +
  +             }
  +
  +             return bResult;
  +     }
  +
  +     // data members
  +
  +     bool m_destroyBlocks;
   
   private:
   
  @@ -221,8 +329,6 @@
        ReusableArenaAllocator<ObjectType>&
        operator=(const ReusableArenaAllocator<ObjectType>&);
   
  -     // Data members...
  -     ReusableArenaBlockType*         m_lastBlockReferenced;
   };
   
   
  
  
  
  1.5       +167 -134  
xml-xalan/c/src/xalanc/PlatformSupport/ReusableArenaBlock.hpp
  
  Index: ReusableArenaBlock.hpp
  ===================================================================
  RCS file: 
/home/cvs/xml-xalan/c/src/xalanc/PlatformSupport/ReusableArenaBlock.hpp,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ReusableArenaBlock.hpp    26 Feb 2004 22:34:18 -0000      1.4
  +++ ReusableArenaBlock.hpp    5 Jul 2004 14:53:51 -0000       1.5
  @@ -18,25 +18,57 @@
   #define REUSABLEARENABLOCK_INCLUDE_GUARD_1357924680
   
   
  +#include <xalanc/PlatformSupport/ArenaBlockBase.hpp>
   
  -#include <xalanc/PlatformSupport/XalanBitmap.hpp>
  -#include <xalanc/PlatformSupport/ArenaBlock.hpp>
   
  +XALAN_CPP_NAMESPACE_BEGIN
   
  +template<bool> struct CompileTimeError;
   
  +template<> struct CompileTimeError<true>{};
   
  -XALAN_CPP_NAMESPACE_BEGIN
  +#define STATIC_CHECK(expr) \
  +     CompileTimeError<(expr) != 0 >()
   
   
  +template <class ObjectType,
  +#if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
  +              class size_Type>
  +#else
  +              class size_Type  = unsigned short >
  +#endif
   
  -template<class ObjectType>
  -class ReusableArenaBlock : public ArenaBlock<ObjectType>
  +class ReusableArenaBlock : public ArenaBlockBase<ObjectType, size_Type>
   {
  +
  +#define VALID_OBJECT_STAMP 0xffddffdd
  +
   public:
   
  -     typedef ArenaBlock<ObjectType>                          BaseClassType;
  +     typedef ArenaBlockBase<ObjectType, size_Type>                           
BaseClassType;
  +
  +     typedef typename BaseClassType::size_type               size_type;
  +
  +     struct NextBlock
  +     {
  +             size_type               next;
  +             const int               verificationStamp;
  +             
  +             NextBlock( size_type _next):
  +                     next(_next),
  +                     verificationStamp(VALID_OBJECT_STAMP)
  +             {
  +             }
  +
  +             bool
  +             isValidFor( size_type  rightBorder ) const
  +             {
  +                     return ( ( verificationStamp == (int)VALID_OBJECT_STAMP 
) &&
  +                             ( next <= rightBorder ) ) ? true : false ;
  +             }
  +     };
  +
   
  -     typedef typename BaseClassType::size_type       size_type;
   
        /*
         * Construct an ArenaBlock of the specified size
  @@ -46,34 +78,87 @@
         */
        ReusableArenaBlock(size_type    theBlockSize) :
                BaseClassType(theBlockSize),
  -             m_freeList(theBlockSize),
  -             m_freeBlockCount(0)
  +             m_firstFreeBlock(0),
  +             m_nextFreeBlock(0)
  +
        {
  +             STATIC_CHECK(sizeof(ObjectType) >= sizeof(NextBlock));
  +             
  +             for( size_type i = 0; i < m_blockSize ; ++i )
  +             {
  +                     new ( reinterpret_cast<NextBlock*>(&m_objectBlock[i]) ) 
NextBlock( (size_type)(i + 1) );
  +             }
        }
   
        ~ReusableArenaBlock()
        {
  -             // Note that this-> is required by template lookup rules.
  -             this->destroyAll();
  +             size_type removedObjects = 0;
  +
  +             NextBlock* pStruct = 0;
  +
  +             for ( size_type i = 0 ; i < m_blockSize && (removedObjects < 
m_objectCount) ; ++i )
  +             {
  +                     pStruct = 
reinterpret_cast<NextBlock*>(&m_objectBlock[i]);
  +
  +                     if ( isOccupiedBlock(pStruct) )
  +                     {
  +                             m_objectBlock[i].~ObjectType();
  +
  +                             ++removedObjects;
  +                     }
  +             }
        }
   
  +
        /*
         * Allocate a block.  Once the object is constructed, you must call
         * commitAllocation().
         *
         * @return a pointer to the new block.
         */
  -     virtual ObjectType*
  +     ObjectType*
        allocateBlock()
        {
  -             if (m_freeBlockCount == 0)
  +             
  +             if ( m_objectCount == m_blockSize )
                {
  -                     return BaseClassType::allocateBlock();
  +                     assert ( m_firstFreeBlock == (m_blockSize + 1) );
  +
  +                     return 0;
                }
                else
                {
  -                     return getNextFromFreeList();
  +                     assert( m_objectCount < m_blockSize );
  +
  +                     ObjectType*             theResult = 0;
  +
  +                     assert ( m_firstFreeBlock <= m_blockSize );
  +                     assert ( m_nextFreeBlock <= m_blockSize );
  +
  +                     // check if any part was allocated but not commited
  +                     if( m_firstFreeBlock != m_nextFreeBlock)
  +                     {
  +                             // return then againg the previouse allocated 
block and wait for commitment
  +                             theResult = m_objectBlock + m_firstFreeBlock;
  +                     }
  +                     else
  +                     {
  +                             theResult = m_objectBlock + m_firstFreeBlock;
  +
  +                             assert(size_type( theResult - m_objectBlock ) < 
m_blockSize);
  +
  +                             m_nextFreeBlock = 
(reinterpret_cast<NextBlock*>(theResult))->next;
  +
  +                             assert ( ( 
reinterpret_cast<NextBlock*>(theResult ))->isValidFor( m_blockSize ) );
  +                             assert ( m_nextFreeBlock <= m_blockSize );
  +
  +                             ++m_objectCount;
  +                     }
  +
  +                     return theResult;
  +
                }
  +             
        }
   
        /*
  @@ -81,44 +166,50 @@
         *
         * @param theBlock the address that was returned by allocateBlock()
         */
  -     virtual void
  -     commitAllocation(ObjectType*    theBlock)
  +     void
  +     commitAllocation(ObjectType* /* theBlock */)
        {
  -             assert(theBlock != 0);
  -             assert(m_freeBlockCount == 0 ||
  -                        theBlock == getNextFromFreeList());
  +             m_firstFreeBlock = m_nextFreeBlock;
   
  -             if (m_freeBlockCount == 0)
  -             {
  -                     BaseClassType::commitAllocation(theBlock);
  -             }
  -             else
  -             {
  -                     removeFromFreeList(theBlock);
  -             }
  +             assert ( m_objectCount <= m_blockSize );
        }
   
        /*
  -      * Find out if there is a block available.
  +      * Destroy the object, and return the block to the free list.
  +      * The behavior is undefined if the object pointed to is not
  +      * owned by the block.
         *
  -      * @return true if one is available, false if not.
  +      * @param theObject the address of the object.
         */
  -     virtual bool
  -     blockAvailable() const
  +     void
  +     destroyObject(ObjectType*       theObject)
        {
  -             return m_freeBlockCount != 0 ? true : 
BaseClassType::blockAvailable();
  -     }
  +             // check if any uncommited block is there, add it to the list
  +             if ( m_firstFreeBlock != m_nextFreeBlock )
  +             {
  +                     // return it to pull of the free blocks
  +                     NextBlock* p = reinterpret_cast<NextBlock*>( 
m_objectBlock + m_firstFreeBlock );
  +
  +                     p = new (p) NextBlock(m_nextFreeBlock);
  +
  +                     m_nextFreeBlock = m_firstFreeBlock;
  +             }
  +
  +             assert(ownsObject(theObject) == true);
  +             assert(shouldDestroyBlock(theObject));
  +
  +             theObject->~ObjectType();
  +
  +             NextBlock* newFreeBlock = 
reinterpret_cast<NextBlock*>(theObject);
  +
  +             newFreeBlock = new (newFreeBlock) NextBlock(m_firstFreeBlock);
  +
  +             m_firstFreeBlock = m_nextFreeBlock = size_type(theObject - 
m_objectBlock);
  +
  +             assert (m_firstFreeBlock <= m_blockSize);
  +
  +             --m_objectCount;
   
  -     /*
  -      * Get the number of objects currently allocated in the
  -      * block.
  -      *
  -      * @return The number of objects allocated.
  -      */
  -     virtual size_type
  -     getCountAllocated() const
  -     {
  -             return BaseClassType::getCountAllocated() - m_freeBlockCount;
        }
   
        /*
  @@ -130,27 +221,12 @@
         * @param theObject the address of the object.
         * @return true if we own the object, false if not.
         */
  -     virtual bool
  +     bool
        ownsObject(const ObjectType*    theObject) const
        {
  -             return BaseClassType::ownsObject(theObject) && 
!isOnFreeList(theObject);
  -     }
  -
  -     /*
  -      * Destroy the object, and return the block to the free list.
  -      * The behavior is undefined if the object pointed to is not
  -      * owned by the block.
  -      *
  -      * @param theObject the address of the object.
  -      */
  -     void
  -     destroyObject(ObjectType*       theObject)
  -     {
  -             assert(ownsObject(theObject) == true);
  -
  -             this->m_destroyFunction(*theObject);
  +             assert ( theObject != 0 );
   
  -             addToFreeList(theObject);
  +             return isOccupiedBlock( reinterpret_cast<const 
NextBlock*>(theObject) );
        }
   
   protected:
  @@ -164,12 +240,20 @@
         * @param theObject the address of the object
         * @return true if block should be destroyed, false if not.
         */
  -     virtual bool
  +     bool
        shouldDestroyBlock(const ObjectType*    theObject) const
        {
  +             assert( size_type(theObject - m_objectBlock) < m_blockSize);
                return !isOnFreeList(theObject);
        }
   
  +     bool
  +     isOccupiedBlock(const NextBlock* block)const
  +     {
  +             assert( block !=0 );
  +
  +             return !( ownsBlock(reinterpret_cast<const ObjectType*>(block)) 
&& block->isValidFor(m_blockSize) );
  +     }
   private:
   
        // Not implemented...
  @@ -193,93 +277,42 @@
        bool
        isOnFreeList(const ObjectType*  theObject) const
        {
  -             if (m_freeBlockCount == 0)
  +             if ( m_objectCount == 0 )
                {
                        return false;
                }
                else
                {
  -                     const size_type         theOffset =
  -                                     this->getBlockOffset(theObject);
  -
  -                     return m_freeList.isSet(theOffset);
  -             }
  -     }
  -
  -     /*
  -      * Add a block to the free list.  The behavior is
  -      * undefined if the object pointed to is not owned by the
  -      * block.
  -      *
  -      * @param theObject the address of the object
  -      */
  -     void
  -     addToFreeList(const ObjectType*         theObject)
  -     {
  -             const size_type         theOffset =
  -                             this->getBlockOffset(theObject);
  +                     ObjectType* pRunPtr = m_objectBlock + m_firstFreeBlock;
   
  -             m_freeList.set(theOffset);
  -
  -             ++m_freeBlockCount;
  -     }
  -
  -     /*
  -      * Remove a block from the free list.  The behavior is
  -      * undefined if the object pointed to is not owned by the
  -      * block.
  -      *
  -      * @param theObject the address of the object
  -      */
  -     void
  -     removeFromFreeList(const ObjectType*    theObject)
  -     {
  -             const size_type         theOffset =
  -                             this->getBlockOffset(theObject);
  -
  -             m_freeList.clear(theOffset);
  -
  -             --m_freeBlockCount;
  -     }
  -
  -     /*
  -      * Get the next block from the free list.  Returns 0 if
  -      * the free list is empty.
  -      *
  -      * @return the address of the block
  -      */
  -     ObjectType*
  -     getNextFromFreeList()
  -     {
  -             ObjectType*             theResult = 0;
  -
  -             if (m_freeBlockCount > 0)
  -             {
  -                     const size_type         theFreeListSize = 
m_freeList.getSize();
  -
  -                     for(size_type i = 0; i < theFreeListSize; ++i)
  +                     for ( int i = 0; i < (m_blockSize - m_objectCount); i++)
                        {
  -                             if (m_freeList.isSet(i) == true)
  +                             assert ( ownsBlock( pRunPtr ) );
  +
  +                             if (pRunPtr == theObject)
  +                             {
  +                                     return true;
  +                             }
  +                             else
                                {
  -                                     // Note that this-> is required by 
template lookup rules.
  -                                     theResult = this->getBlockAddress(i);
  +                                     NextBlock* p = 
reinterpret_cast<NextBlock*>(pRunPtr);
  +
  +                                     assert( p->isValidFor( m_blockSize ) );
   
  -                                     break;
  +                                     pRunPtr = m_objectBlock + p->next ;
                                }
                        }
  -             }
   
  -             return theResult;
  +                     return false;
  +             }
        }
   
  -     // Bitmap which tracks which blocks are not in use
  -     // and that should not be destroyed.
  -     XalanBitmap             m_freeList;
   
  -     // The number of blocks on the free list.)
  -     size_type               m_freeBlockCount;
  -};
  +     size_type               m_firstFreeBlock;
   
  +     size_type               m_nextFreeBlock;
  +
  +};
   
   
   XALAN_CPP_NAMESPACE_END
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to