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