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