1 //===- GCFactory.h --------------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #ifndef MCLD_SUPPORT_GCFACTORY_H_ 10 #define MCLD_SUPPORT_GCFACTORY_H_ 11 #include "mcld/ADT/TypeTraits.h" 12 #include "mcld/Support/Allocators.h" 13 14 #include <assert.h> 15 #include <cstddef> 16 #include <iterator> 17 18 namespace mcld { 19 20 /** \class DataIteratorBase 21 * \brief DataIteratorBase provides the basic functions of DataIterator 22 * @see DataIterator 23 */ 24 template <typename ChunkType> 25 struct DataIteratorBase { 26 public: 27 ChunkType* m_pChunk; 28 unsigned int m_Pos; 29 30 public: DataIteratorBaseDataIteratorBase31 DataIteratorBase(ChunkType* X, unsigned int pPos) 32 : m_pChunk(X), m_Pos(pPos) {} 33 advanceDataIteratorBase34 inline void advance() { 35 ++m_Pos; 36 if ((m_Pos == m_pChunk->bound) && (0 == m_pChunk->next)) 37 return; 38 if (m_Pos == m_pChunk->bound) { 39 m_pChunk = m_pChunk->next; 40 m_Pos = 0; 41 } 42 } 43 44 bool operator==(const DataIteratorBase& y) const { 45 return ((this->m_pChunk == y.m_pChunk) && (this->m_Pos == y.m_Pos)); 46 } 47 48 bool operator!=(const DataIteratorBase& y) const { 49 return ((this->m_pChunk != y.m_pChunk) || (this->m_Pos != y.m_Pos)); 50 } 51 }; 52 53 /** \class DataIterator 54 * \brief DataIterator provides STL compatible iterator for allocators 55 */ 56 template <typename ChunkType, class Traits> 57 class DataIterator : public DataIteratorBase<ChunkType> { 58 public: 59 typedef typename ChunkType::value_type value_type; 60 typedef Traits traits; 61 typedef typename traits::pointer pointer; 62 typedef typename traits::reference reference; 63 typedef DataIterator<ChunkType, Traits> Self; 64 typedef DataIteratorBase<ChunkType> Base; 65 66 typedef typename traits::nonconst_traits nonconst_traits; 67 typedef DataIterator<ChunkType, nonconst_traits> iterator; 68 typedef typename traits::const_traits const_traits; 69 typedef DataIterator<ChunkType, const_traits> const_iterator; 70 typedef std::forward_iterator_tag iterator_category; 71 typedef size_t size_type; 72 typedef ptrdiff_t difference_type; 73 74 public: DataIterator()75 DataIterator() : Base(NULL, 0) {} 76 DataIterator(ChunkType * pChunk,unsigned int pPos)77 DataIterator(ChunkType* pChunk, unsigned int pPos) : Base(pChunk, pPos) {} 78 DataIterator(const DataIterator & pCopy)79 DataIterator(const DataIterator& pCopy) : Base(pCopy.m_pChunk, pCopy.m_Pos) {} 80 ~DataIterator()81 ~DataIterator() {} 82 83 // ----- operators ----- // 84 reference operator*() { 85 assert(this->m_pChunk != NULL && 86 "data iterator goes to a invalid position"); 87 return this->m_pChunk->data[Base::m_Pos]; 88 } 89 90 Self& operator++() { 91 this->Base::advance(); 92 return *this; 93 } 94 95 Self operator++(int) { 96 Self tmp = *this; 97 this->Base::advance(); 98 return tmp; 99 } 100 }; 101 102 template <typename Alloc> 103 class GCFactoryBase : public Alloc { 104 public: 105 typedef DataIterator<typename Alloc::chunk_type, 106 NonConstTraits<typename Alloc::value_type> > iterator; 107 typedef DataIterator<typename Alloc::chunk_type, 108 ConstTraits<typename Alloc::value_type> > const_iterator; 109 110 typedef typename Alloc::value_type value_type; 111 typedef typename Alloc::pointer pointer; 112 typedef typename Alloc::reference reference; 113 typedef typename Alloc::size_type size_type; 114 115 protected: GCFactoryBase()116 GCFactoryBase() : Alloc(), m_NumAllocData(0) {} 117 GCFactoryBase(size_t pNum)118 explicit GCFactoryBase(size_t pNum) : Alloc(pNum), m_NumAllocData(0) {} 119 120 public: ~GCFactoryBase()121 virtual ~GCFactoryBase() { Alloc::clear(); } 122 123 // ----- modifiers ----- // allocate(size_t N)124 value_type* allocate(size_t N) { 125 value_type* result = Alloc::allocate(N); 126 if (result != NULL) 127 m_NumAllocData += N; 128 return result; 129 } 130 allocate()131 value_type* allocate() { 132 ++m_NumAllocData; 133 return Alloc::allocate(); 134 } 135 deallocate(pointer & pPtr,size_type N)136 void deallocate(pointer& pPtr, size_type N) { 137 Alloc::deallocate(pPtr, N); 138 if (pPtr == NULL) 139 m_NumAllocData -= N; 140 } 141 deallocate(pointer & pPtr)142 void deallocate(pointer& pPtr) { 143 Alloc::deallocate(pPtr); 144 if (pPtr == NULL) 145 --m_NumAllocData; 146 } 147 reset()148 void reset() { 149 Alloc::reset(); 150 m_NumAllocData = 0; 151 } 152 153 // ----- iterators ----- // begin()154 iterator begin() { return iterator(Alloc::m_pRoot, 0); } 155 begin()156 const_iterator begin() const { return const_iterator(Alloc::m_pRoot, 0); } 157 end()158 iterator end() { 159 return (Alloc::m_pCurrent) == 0 160 ? begin() 161 : iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound); 162 } 163 end()164 const_iterator end() const { 165 return (Alloc::m_pCurrent) == 0 166 ? begin() 167 : const_iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound); 168 } 169 170 // ----- observers ----- // empty()171 bool empty() const { return Alloc::empty(); } 172 capacity()173 unsigned int capacity() const { return Alloc::max_size(); } 174 size()175 unsigned int size() const { return m_NumAllocData; } 176 177 protected: 178 unsigned int m_NumAllocData; 179 }; 180 181 /** \class GCFactory 182 * \brief GCFactory provides a factory that guaratees to remove all allocated 183 * data. 184 */ 185 template <typename DataType, size_t ChunkSize> 186 class GCFactory : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> > { 187 public: GCFactory()188 GCFactory() : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >() {} 189 }; 190 191 template <typename DataType> 192 class GCFactory<DataType, 0> 193 : public GCFactoryBase<LinearAllocator<DataType, 0> > { 194 public: GCFactory(size_t pNum)195 explicit GCFactory(size_t pNum) 196 : GCFactoryBase<LinearAllocator<DataType, 0> >(pNum) {} 197 }; 198 199 } // namespace mcld 200 201 #endif // MCLD_SUPPORT_GCFACTORY_H_ 202