Home | History | Annotate | Download | only in Support
      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:
     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  */
     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:
     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 
    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:
    128   GCFactoryBase()
    129   : Alloc(), m_NumAllocData(0)
    130   { }
    131 
    132   GCFactoryBase(size_t pNum)
    133   : Alloc(pNum), m_NumAllocData(0)
    134   { }
    135 
    136 public:
    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 
    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:
    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:
    220   GCFactory(size_t pNum)
    221   : GCFactoryBase<LinearAllocator<DataType, 0> >(pNum)
    222   { }
    223 };
    224 
    225 } // namespace of mcld
    226 
    227 #endif
    228 
    229