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