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