| //===- 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_ |