C++程序  |  202行  |  5.33 KB

//===- GCFactory.h --------------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_SUPPORT_GCFACTORY_H_
#define MCLD_SUPPORT_GCFACTORY_H_
#include "mcld/ADT/TypeTraits.h"
#include "mcld/Support/Allocators.h"

#include <assert.h>
#include <cstddef>
#include <iterator>

namespace mcld {

/** \class DataIteratorBase
 *  \brief DataIteratorBase provides the basic functions of DataIterator
 *  @see DataIterator
 */
template <typename ChunkType>
struct DataIteratorBase {
 public:
  ChunkType* m_pChunk;
  unsigned int m_Pos;

 public:
  DataIteratorBase(ChunkType* X, unsigned int pPos)
      : m_pChunk(X), m_Pos(pPos) {}

  inline void advance() {
    ++m_Pos;
    if ((m_Pos == m_pChunk->bound) && (0 == m_pChunk->next))
      return;
    if (m_Pos == m_pChunk->bound) {
      m_pChunk = m_pChunk->next;
      m_Pos = 0;
    }
  }

  bool operator==(const DataIteratorBase& y) const {
    return ((this->m_pChunk == y.m_pChunk) && (this->m_Pos == y.m_Pos));
  }

  bool operator!=(const DataIteratorBase& y) const {
    return ((this->m_pChunk != y.m_pChunk) || (this->m_Pos != y.m_Pos));
  }
};

/** \class DataIterator
 *  \brief DataIterator provides STL compatible iterator for allocators
 */
template <typename ChunkType, class Traits>
class DataIterator : public DataIteratorBase<ChunkType> {
 public:
  typedef typename ChunkType::value_type value_type;
  typedef Traits traits;
  typedef typename traits::pointer pointer;
  typedef typename traits::reference reference;
  typedef DataIterator<ChunkType, Traits> Self;
  typedef DataIteratorBase<ChunkType> Base;

  typedef typename traits::nonconst_traits nonconst_traits;
  typedef DataIterator<ChunkType, nonconst_traits> iterator;
  typedef typename traits::const_traits const_traits;
  typedef DataIterator<ChunkType, const_traits> const_iterator;
  typedef std::forward_iterator_tag iterator_category;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;

 public:
  DataIterator() : Base(NULL, 0) {}

  DataIterator(ChunkType* pChunk, unsigned int pPos) : Base(pChunk, pPos) {}

  DataIterator(const DataIterator& pCopy) : Base(pCopy.m_pChunk, pCopy.m_Pos) {}

  ~DataIterator() {}

  // -----  operators  ----- //
  reference operator*() {
    assert(this->m_pChunk != NULL &&
           "data iterator goes to a invalid position");
    return this->m_pChunk->data[Base::m_Pos];
  }

  Self& operator++() {
    this->Base::advance();
    return *this;
  }

  Self operator++(int) {
    Self tmp = *this;
    this->Base::advance();
    return tmp;
  }
};

template <typename Alloc>
class GCFactoryBase : public Alloc {
 public:
  typedef DataIterator<typename Alloc::chunk_type,
                       NonConstTraits<typename Alloc::value_type> > iterator;
  typedef DataIterator<typename Alloc::chunk_type,
                       ConstTraits<typename Alloc::value_type> > const_iterator;

  typedef typename Alloc::value_type value_type;
  typedef typename Alloc::pointer pointer;
  typedef typename Alloc::reference reference;
  typedef typename Alloc::size_type size_type;

 protected:
  GCFactoryBase() : Alloc(), m_NumAllocData(0) {}

  explicit GCFactoryBase(size_t pNum) : Alloc(pNum), m_NumAllocData(0) {}

 public:
  virtual ~GCFactoryBase() { Alloc::clear(); }

  // -----  modifiers  ----- //
  value_type* allocate(size_t N) {
    value_type* result = Alloc::allocate(N);
    if (result != NULL)
      m_NumAllocData += N;
    return result;
  }

  value_type* allocate() {
    ++m_NumAllocData;
    return Alloc::allocate();
  }

  void deallocate(pointer& pPtr, size_type N) {
    Alloc::deallocate(pPtr, N);
    if (pPtr == NULL)
      m_NumAllocData -= N;
  }

  void deallocate(pointer& pPtr) {
    Alloc::deallocate(pPtr);
    if (pPtr == NULL)
      --m_NumAllocData;
  }

  void reset() {
    Alloc::reset();
    m_NumAllocData = 0;
  }

  // -----  iterators  ----- //
  iterator begin() { return iterator(Alloc::m_pRoot, 0); }

  const_iterator begin() const { return const_iterator(Alloc::m_pRoot, 0); }

  iterator end() {
    return (Alloc::m_pCurrent) == 0
               ? begin()
               : iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound);
  }

  const_iterator end() const {
    return (Alloc::m_pCurrent) == 0
               ? begin()
               : const_iterator(Alloc::m_pCurrent, Alloc::m_pCurrent->bound);
  }

  // -----  observers  ----- //
  bool empty() const { return Alloc::empty(); }

  unsigned int capacity() const { return Alloc::max_size(); }

  unsigned int size() const { return m_NumAllocData; }

 protected:
  unsigned int m_NumAllocData;
};

/** \class GCFactory
 *  \brief GCFactory provides a factory that guaratees to remove all allocated
 *  data.
 */
template <typename DataType, size_t ChunkSize>
class GCFactory : public GCFactoryBase<LinearAllocator<DataType, ChunkSize> > {
 public:
  GCFactory() : GCFactoryBase<LinearAllocator<DataType, ChunkSize> >() {}
};

template <typename DataType>
class GCFactory<DataType, 0>
    : public GCFactoryBase<LinearAllocator<DataType, 0> > {
 public:
  explicit GCFactory(size_t pNum)
     : GCFactoryBase<LinearAllocator<DataType, 0> >(pNum) {}
};

}  // namespace mcld

#endif  // MCLD_SUPPORT_GCFACTORY_H_