//===- GCFactory.h --------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_GC_FACTORY_H
#define MCLD_GC_FACTORY_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include "mcld/ADT/TypeTraits.h"
#include "mcld/Support/Allocators.h"
#include <assert.h>
#include <cstddef>
#include <iterator>
namespace mcld
{
/** \class DataIteratorBase
* \brief DataIteratorBase provides the basic functions of DataIterator
* @see DataIterator
*/
template<typename ChunkType>
struct DataIteratorBase
{
public:
ChunkType* m_pChunk;
unsigned int m_Pos;
public:
DataIteratorBase(ChunkType* X, unsigned int pPos)
: m_pChunk(X), m_Pos(pPos)
{ }
inline void advance() {
++m_Pos;
if ((m_Pos == m_pChunk->bound) && (0 == m_pChunk->next))
return;
if (m_Pos == m_pChunk->bound) {
m_pChunk = m_pChunk->next;
m_Pos = 0;
}
}
bool operator==(const DataIteratorBase& y) const
{ return ((this->m_pChunk == y.m_pChunk) && (this->m_Pos == y.m_Pos)); }
bool operator!=(const DataIteratorBase& y) const
{ return ((this->m_pChunk != y.m_pChunk) || (this->m_Pos != y.m_Pos)); }
};
/** \class DataIterator
* \brief DataIterator provides STL compatible iterator for allocators
*/
template<typename ChunkType, class Traits>
class DataIterator : public DataIteratorBase<ChunkType>
{
public:
typedef typename ChunkType::value_type value_type;
typedef Traits traits;
typedef typename traits::pointer pointer;
typedef typename traits::reference reference;
typedef DataIterator<ChunkType, Traits> Self;
typedef DataIteratorBase<ChunkType> Base;
typedef typename traits::nonconst_traits nonconst_traits;
typedef DataIterator<ChunkType, nonconst_traits> iterator;
typedef typename traits::const_traits const_traits;
typedef DataIterator<ChunkType, const_traits> const_iterator;
typedef std::forward_iterator_tag iterator_category;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
public:
DataIterator()
: Base(0, 0)
{ }
DataIterator(ChunkType* pChunk, unsigned int pPos)
: Base(pChunk, pPos)
{ }
DataIterator(const DataIterator& pCopy)
: Base(pCopy.m_pChunk, pCopy.m_Pos)
{ }
~DataIterator()
{ }
// ----- operators ----- //
reference operator*() {
if (0 == this->m_pChunk)
assert(0 && "data iterator goes to a invalid position");
return this->m_pChunk->data[Base::m_Pos];
}
Self& operator++() {
this->Base::advance();
return *this;
}
Self operator++(int) {
Self tmp = *this;
this->Base::advance();
return tmp;
}
};
template<typename Alloc>
class GCFactoryBase : public Alloc
{
public:
typedef DataIterator<typename Alloc::chunk_type,
NonConstTraits<
typename Alloc::value_type> > iterator;
typedef DataIterator<typename Alloc::chunk_type,
ConstTraits<
typename Alloc::value_type> > const_iterator;
typedef typename Alloc::value_type value_type;
typedef typename Alloc::pointer pointer;
typedef typename Alloc::reference reference;
typedef typename Alloc::size_type size_type;
protected:
GCFactoryBase()
: Alloc(), m_NumAllocData(0)
{ }
GCFactoryBase(size_t pNum)
: Alloc(pNum), m_NumAllocData(0)
{ }
public:
virtual ~GCFactoryBase()
{ Alloc::clear(); }
// ----- modifiers ----- //
value_type* allocate(size_t N) {
value_type* result = Alloc::allocate(N);
if (0 != result)
m_NumAllocData += N;
return result;
}
value_type* allocate() {
++m_NumAllocData;
return Alloc::allocate();
}
void deallocate(pointer &pPtr, size_type N) {
Alloc::deallocate(pPtr, N);
if (0 == pPtr)
m_NumAllocData -= N;
}
void deallocate(pointer &pPtr) {
Alloc::deallocate(pPtr);
if (0 == pPtr)
--m_NumAllocData;
}
void reset() {
Alloc::reset();
m_NumAllocData = 0;
}
// ----- iterators ----- //
iterator begin()
{ return iterator(Alloc::m_pRoot, 0); }
const_iterator begin() const
{ return const_iterator(Alloc::m_pRoot, 0); }
iterator end() {
return (0 == Alloc::m_pCurrent)?
begin():
iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound);
}
const_iterator end() const {
return (0 == Alloc::m_pCurrent)?
begin():
const_iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound);
}
// ----- observers ----- //
bool empty() const
{ return Alloc::empty(); }
unsigned int capacity() const
{ return Alloc::max_size(); }
unsigned int size() const
{ return m_NumAllocData; }
protected:
unsigned int m_NumAllocData;
};
/** \class GCFactory
* \brief GCFactory provides a factory that guaratees to remove all allocated
* data.
*/
template<typename DataType, size_t ChunkSize>
class GCFactory : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> >
{
public:
GCFactory()
: GCFactoryBase<LinearAllocator<DataType, ChunkSize> >()
{ }
};
template<typename DataType>
class GCFactory<DataType, 0> : public GCFactoryBase<LinearAllocator<DataType, 0> >
{
public:
GCFactory(size_t pNum)
: GCFactoryBase<LinearAllocator<DataType, 0> >(pNum)
{ }
};
} // namespace of mcld
#endif