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 21 /** \class DataIteratorBase 22 * \brief DataIteratorBase provides the basic functions of DataIterator 23 * @see DataIterator 24 */ 25 template<typename ChunkType> 26 struct DataIteratorBase 27 { 28 public: 29 ChunkType* m_pChunk; 30 unsigned int m_Pos; 31 32 public: DataIteratorBaseDataIteratorBase33 DataIteratorBase(ChunkType* X, unsigned int pPos) 34 : m_pChunk(X), m_Pos(pPos) 35 { } 36 advanceDataIteratorBase37 inline void advance() { 38 ++m_Pos; 39 if ((m_Pos == m_pChunk->bound) && (0 == m_pChunk->next)) 40 return; 41 if (m_Pos == m_pChunk->bound) { 42 m_pChunk = m_pChunk->next; 43 m_Pos = 0; 44 } 45 } 46 47 bool operator==(const DataIteratorBase& y) const 48 { return ((this->m_pChunk == y.m_pChunk) && (this->m_Pos == y.m_Pos)); } 49 50 bool operator!=(const DataIteratorBase& y) const 51 { return ((this->m_pChunk != y.m_pChunk) || (this->m_Pos != y.m_Pos)); } 52 }; 53 54 /** \class DataIterator 55 * \brief DataIterator provides STL compatible iterator for allocators 56 */ 57 template<typename ChunkType, class Traits> 58 class DataIterator : public DataIteratorBase<ChunkType> 59 { 60 public: 61 typedef typename ChunkType::value_type value_type; 62 typedef Traits traits; 63 typedef typename traits::pointer pointer; 64 typedef typename traits::reference reference; 65 typedef DataIterator<ChunkType, Traits> Self; 66 typedef DataIteratorBase<ChunkType> Base; 67 68 typedef typename traits::nonconst_traits nonconst_traits; 69 typedef DataIterator<ChunkType, nonconst_traits> iterator; 70 typedef typename traits::const_traits const_traits; 71 typedef DataIterator<ChunkType, const_traits> const_iterator; 72 typedef std::forward_iterator_tag iterator_category; 73 typedef size_t size_type; 74 typedef ptrdiff_t difference_type; 75 76 public: DataIterator()77 DataIterator() 78 : Base(0, 0) 79 { } 80 DataIterator(ChunkType * pChunk,unsigned int pPos)81 DataIterator(ChunkType* pChunk, unsigned int pPos) 82 : Base(pChunk, pPos) 83 { } 84 DataIterator(const DataIterator & pCopy)85 DataIterator(const DataIterator& pCopy) 86 : Base(pCopy.m_pChunk, pCopy.m_Pos) 87 { } 88 ~DataIterator()89 ~DataIterator() 90 { } 91 92 // ----- operators ----- // 93 reference operator*() { 94 if (0 == this->m_pChunk) 95 assert(0 && "data iterator goes to a invalid position"); 96 return this->m_pChunk->data[Base::m_Pos]; 97 } 98 99 Self& operator++() { 100 this->Base::advance(); 101 return *this; 102 } 103 104 Self operator++(int) { 105 Self tmp = *this; 106 this->Base::advance(); 107 return tmp; 108 } 109 }; 110 111 template<typename Alloc> 112 class GCFactoryBase : public Alloc 113 { 114 public: 115 typedef DataIterator<typename Alloc::chunk_type, 116 NonConstTraits< 117 typename Alloc::value_type> > iterator; 118 typedef DataIterator<typename Alloc::chunk_type, 119 ConstTraits< 120 typename Alloc::value_type> > const_iterator; 121 122 typedef typename Alloc::value_type value_type; 123 typedef typename Alloc::pointer pointer; 124 typedef typename Alloc::reference reference; 125 typedef typename Alloc::size_type size_type; 126 127 protected: GCFactoryBase()128 GCFactoryBase() 129 : Alloc(), m_NumAllocData(0) 130 { } 131 GCFactoryBase(size_t pNum)132 GCFactoryBase(size_t pNum) 133 : Alloc(pNum), m_NumAllocData(0) 134 { } 135 136 public: ~GCFactoryBase()137 virtual ~GCFactoryBase() 138 { Alloc::clear(); } 139 140 // ----- modifiers ----- // allocate(size_t N)141 value_type* allocate(size_t N) { 142 value_type* result = Alloc::allocate(N); 143 if (0 != result) 144 m_NumAllocData += N; 145 return result; 146 } 147 allocate()148 value_type* allocate() { 149 ++m_NumAllocData; 150 return Alloc::allocate(); 151 } 152 deallocate(pointer & pPtr,size_type N)153 void deallocate(pointer &pPtr, size_type N) { 154 Alloc::deallocate(pPtr, N); 155 if (0 == pPtr) 156 m_NumAllocData -= N; 157 } 158 deallocate(pointer & pPtr)159 void deallocate(pointer &pPtr) { 160 Alloc::deallocate(pPtr); 161 if (0 == pPtr) 162 --m_NumAllocData; 163 } 164 reset()165 void reset() { 166 Alloc::reset(); 167 m_NumAllocData = 0; 168 } 169 170 // ----- iterators ----- // begin()171 iterator begin() 172 { return iterator(Alloc::m_pRoot, 0); } 173 begin()174 const_iterator begin() const 175 { return const_iterator(Alloc::m_pRoot, 0); } 176 end()177 iterator end() { 178 return (0 == Alloc::m_pCurrent)? 179 begin(): 180 iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound); 181 } 182 end()183 const_iterator end() const { 184 return (0 == Alloc::m_pCurrent)? 185 begin(): 186 const_iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound); 187 } 188 189 // ----- observers ----- // empty()190 bool empty() const 191 { return Alloc::empty(); } 192 capacity()193 unsigned int capacity() const 194 { return Alloc::max_size(); } 195 size()196 unsigned int size() const 197 { return m_NumAllocData; } 198 199 protected: 200 unsigned int m_NumAllocData; 201 }; 202 203 /** \class GCFactory 204 * \brief GCFactory provides a factory that guaratees to remove all allocated 205 * data. 206 */ 207 template<typename DataType, size_t ChunkSize> 208 class GCFactory : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> > 209 { 210 public: GCFactory()211 GCFactory() 212 : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >() 213 { } 214 }; 215 216 template<typename DataType> 217 class GCFactory<DataType, 0> : public GCFactoryBase<LinearAllocator<DataType, 0> > 218 { 219 public: GCFactory(size_t pNum)220 GCFactory(size_t pNum) 221 : GCFactoryBase<LinearAllocator<DataType, 0> >(pNum) 222 { } 223 }; 224 225 } // namespace of mcld 226 227 #endif 228 229