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 /** \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:
     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  */
     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:
     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 
    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:
    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  */
    185 template <typename DataType, size_t ChunkSize>
    186 class GCFactory : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> > {
    187  public:
    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:
    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