blob: 88634623aaebe7370ac4b3ddacb6a0088a0a0448 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !defined(ARENABLOCKBASE_INCLUDE_GUARD_1357924680)
#define ARENABLOCKBASE_INCLUDE_GUARD_1357924680
#include <cassert>
#include <functional>
//#include <memory>
#include <xalanc/Include/XalanMemoryManagement.hpp>
#if !defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION)
#include <xalanc/PlatformSupport/XalanAllocator.hpp>
#endif
namespace XALAN_CPP_NAMESPACE {
#if defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION)
template <class Type>
class ArenaBlockAllocator
{
public:
typedef typename 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(MemoryManager& theManager) :
m_memoryManager(theManager)
{
}
~ArenaBlockAllocator()
{
}
MemoryManager&
getMemoryManager()
{
return m_memoryManager;
}
pointer
allocate(
size_type size,
const void* /* hint */ = 0)
{
return (pointer)m_memoryManager.allocate(size * sizeof(Type));
}
void
deallocate(
pointer p,
size_type /* n */)
{
if(p != 0)
{
m_memoryManager.deallocate(p);
}
}
private:
// not defined
ArenaBlockAllocator(const ArenaBlockAllocator<Type>&);
ArenaBlockAllocator<Type>&
operator=(const ArenaBlockAllocator<Type>&);
MemoryManager& m_memoryManager;
};
#endif
template<class ObjectType,
#if defined(XALAN_NO_DEFAULT_TEMPLATE_ARGUMENTS)
class SizeType>
#else
class SizeType = size_t>
#endif
class ArenaBlockBase
{
public:
typedef ArenaBlockBase<ObjectType, SizeType> ThisType;
#if defined(XALAN_NO_SELECTIVE_TEMPLATE_INSTANTIATION)
typedef ArenaBlockAllocator<ObjectType> AllocatorType;
#else
typedef XalanAllocator<ObjectType> AllocatorType;
#endif
typedef SizeType size_type;
MemoryManager&
getMemoryManager()
{
return m_allocator.getMemoryManager();
}
/*
* Find out if there is a block available.
*
* @return true if one is available, false if not.
*/
bool
blockAvailable() const
{
return m_objectCount < m_blockSize ? true : false;
}
/*
* Find out if there are any block is allocated
*
* @return true if one is available, false if not.
*/
bool
isEmpty() const
{
return m_objectCount == 0 ? true : false;
}
/*
* Get the number of objects currently allocated in the
* block.
*
* @return The number of objects allocated.
*/
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 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
{
return isInBorders(theObject, m_blockSize);
}
protected:
ArenaBlockBase(
MemoryManager& theManager,
size_type theBlockSize) :
m_allocator(theManager),
m_objectCount(0),
m_blockSize(theBlockSize),
m_objectBlock(m_allocator.allocate(m_blockSize))
{
assert(theBlockSize > 0);
assert(m_objectBlock != 0);
}
~ArenaBlockBase()
{
// Release the memory...
m_allocator.deallocate(m_objectBlock, m_blockSize);
}
/*
* Determine if this block is located between beginning of the array
* and the "rightBorder" array member (not included)
* @param theObject the address of the object
* rightBorder the right
* @return true if we own the object block, false if not.
*/
bool
isInBorders(
const ObjectType* theObject,
size_type rightBoundary) const
{
if ( rightBoundary > m_blockSize )
{
rightBoundary = m_blockSize;
}
// Use less<>, since it's guaranteed to do pointer
// comparisons correctly...
std::less<const ObjectType*> functor;
if (functor(theObject, m_objectBlock) == false &&
functor(theObject, m_objectBlock + rightBoundary) == true)
{
return true;
}
else
{
return false;
}
}
/*
* 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) / sizeof(ObjectType) ) < 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
{
assert(theOffset < m_blockSize);
return m_objectBlock + theOffset;
}
// data members...
AllocatorType m_allocator;
size_type m_objectCount;
const size_type m_blockSize;
ObjectType* m_objectBlock;
private:
// Not implemented...
ArenaBlockBase(const ThisType&);
ThisType&
operator=(const ThisType&);
bool
operator==(const ThisType&) const;
};
}
#endif // !defined(ARENABLOCKBASE_INCLUDE_GUARD_1357924680)