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 /** \class DataIteratorBase
21  *  \brief DataIteratorBase provides the basic functions of DataIterator
22  *  @see DataIterator
23  */
24 template <typename ChunkType>
25 struct DataIteratorBase {
26  public:
27   ChunkType* m_pChunk;
28   unsigned int m_Pos;
29 
30  public:
DataIteratorBaseDataIteratorBase31   DataIteratorBase(ChunkType* X, unsigned int pPos)
32       : m_pChunk(X), m_Pos(pPos) {}
33 
advanceDataIteratorBase34   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  */
56 template <typename ChunkType, class Traits>
57 class 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:
DataIterator()75   DataIterator() : Base(NULL, 0) {}
76 
DataIterator(ChunkType * pChunk,unsigned int pPos)77   DataIterator(ChunkType* pChunk, unsigned int pPos) : Base(pChunk, pPos) {}
78 
DataIterator(const DataIterator & pCopy)79   DataIterator(const DataIterator& pCopy) : Base(pCopy.m_pChunk, pCopy.m_Pos) {}
80 
~DataIterator()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 
102 template <typename Alloc>
103 class 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:
GCFactoryBase()116   GCFactoryBase() : Alloc(), m_NumAllocData(0) {}
117 
GCFactoryBase(size_t pNum)118   explicit GCFactoryBase(size_t pNum) : Alloc(pNum), m_NumAllocData(0) {}
119 
120  public:
~GCFactoryBase()121   virtual ~GCFactoryBase() { Alloc::clear(); }
122 
123   // -----  modifiers  ----- //
allocate(size_t N)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 
allocate()131   value_type* allocate() {
132     ++m_NumAllocData;
133     return Alloc::allocate();
134   }
135 
deallocate(pointer & pPtr,size_type N)136   void deallocate(pointer& pPtr, size_type N) {
137     Alloc::deallocate(pPtr, N);
138     if (pPtr == NULL)
139       m_NumAllocData -= N;
140   }
141 
deallocate(pointer & pPtr)142   void deallocate(pointer& pPtr) {
143     Alloc::deallocate(pPtr);
144     if (pPtr == NULL)
145       --m_NumAllocData;
146   }
147 
reset()148   void reset() {
149     Alloc::reset();
150     m_NumAllocData = 0;
151   }
152 
153   // -----  iterators  ----- //
begin()154   iterator begin() { return iterator(Alloc::m_pRoot, 0); }
155 
begin()156   const_iterator begin() const { return const_iterator(Alloc::m_pRoot, 0); }
157 
end()158   iterator end() {
159     return (Alloc::m_pCurrent) == 0
160                ? begin()
161                : iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound);
162   }
163 
end()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  ----- //
empty()171   bool empty() const { return Alloc::empty(); }
172 
capacity()173   unsigned int capacity() const { return Alloc::max_size(); }
174 
size()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  */
185 template <typename DataType, size_t ChunkSize>
186 class GCFactory : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> > {
187  public:
GCFactory()188   GCFactory() : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >() {}
189 };
190 
191 template <typename DataType>
192 class GCFactory<DataType, 0>
193     : public GCFactoryBase<LinearAllocator<DataType, 0> > {
194  public:
GCFactory(size_t pNum)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