blob: fd86cddd75e57f1cc1a87f55d32c68423f86b5c5 [file] [log] [blame]
//===- GCFactory.h --------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_SUPPORT_GCFACTORY_H_
#define MCLD_SUPPORT_GCFACTORY_H_
#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(NULL, 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*() {
assert(this->m_pChunk != NULL &&
"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) {}
explicit 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 (result != NULL)
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 (pPtr == NULL)
m_NumAllocData -= N;
}
void deallocate(pointer& pPtr) {
Alloc::deallocate(pPtr);
if (pPtr == NULL)
--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 (Alloc::m_pCurrent) == 0
? begin()
: iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound);
}
const_iterator end() const {
return (Alloc::m_pCurrent) == 0
? 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:
explicit GCFactory(size_t pNum)
: GCFactoryBase<LinearAllocator<DataType, 0> >(pNum) {}
};
} // namespace mcld
#endif // MCLD_SUPPORT_GCFACTORY_H_