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