GCFactory.h revision f767be5432ccac097334be48698e48621d730190
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
21namespace mcld
22{
23
24/** \class DataIteratorBase
25 *  \brief DataIteratorBase provides the basic functions of DataIterator
26 *  @see DataIterator
27 */
28template<typename ChunkType>
29struct DataIteratorBase
30{
31public:
32  ChunkType* m_pChunk;
33  unsigned int m_Pos;
34
35public:
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 */
60template<typename ChunkType, class Traits>
61class DataIterator : public DataIteratorBase<ChunkType>
62{
63public:
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
79public:
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
114template<typename Alloc>
115class GCFactoryBase : public Alloc
116{
117public:
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
130protected:
131  GCFactoryBase()
132  : Alloc(), m_NumAllocData(0)
133  { }
134
135  GCFactoryBase(size_t pNum)
136  : Alloc(pNum), m_NumAllocData(0)
137  { }
138
139public:
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
202protected:
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 */
210template<typename DataType, size_t ChunkSize>
211class GCFactory : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> >
212{
213public:
214  GCFactory()
215  : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >()
216  { }
217};
218
219template<typename DataType>
220class GCFactory<DataType, 0> : public GCFactoryBase<LinearAllocator<DataType, 0> >
221{
222public:
223  GCFactory(size_t pNum)
224  : GCFactoryBase<LinearAllocator<DataType, 0> >(pNum)
225  { }
226};
227
228} // namespace of mcld
229
230#endif
231