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]