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 18namespace mcld 19{ 20 21/** \class DataIteratorBase 22 * \brief DataIteratorBase provides the basic functions of DataIterator 23 * @see DataIterator 24 */ 25template<typename ChunkType> 26struct DataIteratorBase 27{ 28public: 29 ChunkType* m_pChunk; 30 unsigned int m_Pos; 31 32public: 33 DataIteratorBase(ChunkType* X, unsigned int pPos) 34 : m_pChunk(X), m_Pos(pPos) 35 { } 36 37 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 */ 57template<typename ChunkType, class Traits> 58class DataIterator : public DataIteratorBase<ChunkType> 59{ 60public: 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 76public: 77 DataIterator() 78 : Base(0, 0) 79 { } 80 81 DataIterator(ChunkType* pChunk, unsigned int pPos) 82 : Base(pChunk, pPos) 83 { } 84 85 DataIterator(const DataIterator& pCopy) 86 : Base(pCopy.m_pChunk, pCopy.m_Pos) 87 { } 88 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 111template<typename Alloc> 112class GCFactoryBase : public Alloc 113{ 114public: 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 127protected: 128 GCFactoryBase() 129 : Alloc(), m_NumAllocData(0) 130 { } 131 132 GCFactoryBase(size_t pNum) 133 : Alloc(pNum), m_NumAllocData(0) 134 { } 135 136public: 137 virtual ~GCFactoryBase() 138 { Alloc::clear(); } 139 140 // ----- modifiers ----- // 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 148 value_type* allocate() { 149 ++m_NumAllocData; 150 return Alloc::allocate(); 151 } 152 153 void deallocate(pointer &pPtr, size_type N) { 154 Alloc::deallocate(pPtr, N); 155 if (0 == pPtr) 156 m_NumAllocData -= N; 157 } 158 159 void deallocate(pointer &pPtr) { 160 Alloc::deallocate(pPtr); 161 if (0 == pPtr) 162 --m_NumAllocData; 163 } 164 165 void reset() { 166 Alloc::reset(); 167 m_NumAllocData = 0; 168 } 169 170 // ----- iterators ----- // 171 iterator begin() 172 { return iterator(Alloc::m_pRoot, 0); } 173 174 const_iterator begin() const 175 { return const_iterator(Alloc::m_pRoot, 0); } 176 177 iterator end() { 178 return (0 == Alloc::m_pCurrent)? 179 begin(): 180 iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound); 181 } 182 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 ----- // 190 bool empty() const 191 { return Alloc::empty(); } 192 193 unsigned int capacity() const 194 { return Alloc::max_size(); } 195 196 unsigned int size() const 197 { return m_NumAllocData; } 198 199protected: 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 */ 207template<typename DataType, size_t ChunkSize> 208class GCFactory : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> > 209{ 210public: 211 GCFactory() 212 : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >() 213 { } 214}; 215 216template<typename DataType> 217class GCFactory<DataType, 0> : public GCFactoryBase<LinearAllocator<DataType, 0> > 218{ 219public: 220 GCFactory(size_t pNum) 221 : GCFactoryBase<LinearAllocator<DataType, 0> >(pNum) 222 { } 223}; 224 225} // namespace of mcld 226 227#endif 228 229