Home | History | Annotate | Download | only in unit
      1 #ifndef STLPORT_UNIT_TEST_STACK_ALLOCATOR_H
      2 #define STLPORT_UNIT_TEST_STACK_ALLOCATOR_H
      3 
      4 #include <algorithm>
      5 
      6 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
      7 //For bad_alloc:
      8 #  include <new>
      9 #endif
     10 
     11 #undef __STD
     12 #if !defined (STLPORT) || defined (_STLP_USE_NAMESPACES)
     13 #  define __STD std::
     14 #else
     15 #  define __STD
     16 #endif
     17 
     18 struct State {
     19   char *m_beg, *m_end, *m_cur;
     20   bool m_isOk, m_swaped;
     21   int m_nbAlloc;
     22 
     23   //The following members are shared among all StackAllocator instance created from
     24   //a reference StackAllocator instance:
     25   char **m_sharedCur;
     26   bool *m_sharedOk;
     27   int *m_sharedNbAlloc;
     28 
     29 #if defined (__DMC__)
     30   State(){}
     31 #endif
     32 
     33   State(char *beg, char *end)
     34     : m_beg(beg), m_end(end), m_cur(m_beg), m_isOk(true), m_swaped(false), m_nbAlloc(0),
     35       m_sharedCur(&m_cur), m_sharedOk(&m_isOk), m_sharedNbAlloc(&m_nbAlloc) {}
     36 
     37   State(const State& other)
     38   : m_beg(other.m_beg), m_end(other.m_end), m_cur(0),
     39     m_isOk(true), m_swaped(other.m_swaped), m_nbAlloc(0),
     40     m_sharedCur(other.m_sharedCur), m_sharedOk(other.m_sharedOk),
     41     m_sharedNbAlloc(other.m_sharedNbAlloc) {}
     42 };
     43 
     44 /* This allocator is not thread safe:
     45  */
     46 template <class _Tp>
     47 struct StackAllocator
     48 #if defined (STLPORT) && \
     49     defined (_STLP_USE_PARTIAL_SPEC_WORKAROUND) && !defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER)
     50   //Special Borland workaround that have problem with function
     51   //overloading when one of the overloaded version is a template
     52   //one. This is the case for the std::swap function.
     53   : public __STD __stlport_class<StackAllocator<_Tp> >
     54 #endif
     55 {
     56   typedef _Tp        value_type;
     57   typedef value_type *       pointer;
     58   typedef const _Tp* const_pointer;
     59   typedef _Tp&       reference;
     60   typedef const _Tp& const_reference;
     61   typedef size_t     size_type;
     62   typedef ptrdiff_t  difference_type;
     63 
     64 #if defined (__DMC__)
     65   StackAllocator(){}
     66 #endif
     67 
     68   StackAllocator(char *beg, char *end)
     69     : m_state(beg, end) {}
     70 
     71   const State& getState() const { return m_state; }
     72 #if !defined (STLPORT) || defined (_STLP_MEMBER_TEMPLATES)
     73   template <class _OtherTp>
     74   StackAllocator(StackAllocator<_OtherTp> const& other)
     75     : m_state(other.getState()) {}
     76 #else
     77   StackAllocator(const State& state)
     78     : m_state(state) {}
     79 #endif
     80 
     81 #if !defined (STLPORT) || defined (_STLP_MEMBER_TEMPLATE_CLASSES)
     82   template <class _Other>
     83   struct rebind {
     84     typedef StackAllocator<_Other> other;
     85   };
     86 #endif
     87 
     88   _Tp* allocate(size_type n, void* = 0) {
     89     if (n == 0)
     90       return 0;
     91 
     92     ++(*m_state.m_sharedNbAlloc);
     93 
     94     if (*m_state.m_sharedCur + (n * sizeof(_Tp)) < m_state.m_end) {
     95       char *ret = *m_state.m_sharedCur;
     96       *m_state.m_sharedCur += n * sizeof(_Tp);
     97       return reinterpret_cast<_Tp*>(ret);
     98     }
     99 #if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
    100     throw __STD bad_alloc();
    101 #  if defined (__DMC__)
    102     return 0;
    103 #  endif
    104 #else
    105     return 0;
    106 #endif
    107   }
    108 
    109 #if defined (STLPORT) && \
    110     defined (_STLP_USE_PARTIAL_SPEC_WORKAROUND) && !defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER)
    111   //Necessary extension to make StackAllocator a real STLport allocator
    112   //implementation:
    113   _Tp* _M_allocate(size_type n, size_type &new_n) {
    114     new_n = n;
    115     return allocate(n);
    116   }
    117 #endif
    118 
    119   void deallocate(pointer p, size_type n) {
    120     if (p == 0)
    121       return;
    122 
    123     --(*m_state.m_sharedNbAlloc);
    124 
    125     if ((char*)p == (*m_state.m_sharedCur - n * sizeof(_Tp))) {
    126       *m_state.m_sharedCur -= n * sizeof(_Tp);
    127     }
    128 
    129     if ((char*)p < m_state.m_beg || (char*)p >= m_state.m_end) {
    130       //An object has been returned to the bad allocator instance:
    131       *m_state.m_sharedOk = false;
    132     }
    133   }
    134 
    135   pointer address(reference __x) const {return &__x;}
    136   const_pointer address(const_reference __x) const { return &__x; }
    137   size_type max_size() const { return m_state.m_end - *m_state.m_sharedCur; }
    138   void construct(pointer __p, const_reference __val) { new(__p) _Tp(__val);  }
    139   void destroy(pointer __p) { __p->~_Tp(); }
    140 
    141   bool ok() const { return m_state.m_isOk && (m_state.m_nbAlloc == 0); }
    142   void reset () {
    143     m_state.m_cur = m_state.m_beg;
    144     m_state.m_isOk = true;
    145     m_state.m_swaped = false;
    146   }
    147   bool swaped() const { return m_state.m_swaped; }
    148   void swap(StackAllocator &other) {
    149     __STD swap(m_state, other.m_state);
    150     m_state.m_swaped = true;
    151     other.m_state.m_swaped = true;
    152   }
    153 #if defined (STLPORT) && \
    154     defined (_STLP_USE_PARTIAL_SPEC_WORKAROUND) && !defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER)
    155   void _M_swap_workaround(StackAllocator& __x) { swap(__x); }
    156 #endif
    157 
    158   //2 StackAllocator instance are identical if they are built on top
    159   //of the same buffer.
    160   bool operator == (StackAllocator const& other) const
    161   { return m_state.m_beg == other.m_state.m_beg; }
    162 
    163   bool operator != (StackAllocator const& other) const
    164   { return !(*this == other); }
    165 
    166 private:
    167   State m_state;
    168 };
    169 
    170 #if !defined (STLPORT) || defined (_STLP_USE_NAMESPACES)
    171 namespace std {
    172 #endif
    173 
    174 #  if defined (STLPORT) && (defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || !defined (_STLP_MEMBER_TEMPLATES))
    175 template <class _Tp1, class _Tp2>
    176 inline StackAllocator<_Tp2>&
    177 __stl_alloc_rebind(StackAllocator<_Tp1>& __a, const _Tp2*) {  return (StackAllocator<_Tp2>&)(__a); }
    178 template <class _Tp1, class _Tp2>
    179 inline StackAllocator<_Tp2>
    180 __stl_alloc_create(const StackAllocator<_Tp1>& __a, const _Tp2*) { return StackAllocator<_Tp2>(__a.getState()); }
    181 #  endif
    182 
    183 #  if !defined (STLPORT) || defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER)
    184   template <class _Tp>
    185   inline void swap(StackAllocator<_Tp>& __a, StackAllocator<_Tp>& __b)
    186   { __a.swap(__b); }
    187 #  elif !defined (_STLP_USE_PARTIAL_SPEC_WORKAROUND)
    188 //The following overloads depends on instanciation, if new unit tests are written
    189 //with new StackAllocator instanciations associated swap overload should also be
    190 //written
    191 inline void swap(StackAllocator<int>& __a, StackAllocator<int>& __b)
    192 { __a.swap(__b); }
    193 inline void swap(StackAllocator<char>& __a, StackAllocator<char>& __b)
    194 { __a.swap(__b); }
    195 inline void swap(StackAllocator<pair<const int, int> >& __a,
    196                  StackAllocator<pair<const int, int> >& __b)
    197 { __a.swap(__b); }
    198 #  endif
    199 
    200 #if !defined (STLPORT) || defined (_STLP_USE_NAMESPACES)
    201 }
    202 #endif
    203 
    204 #undef __STD
    205 
    206 #endif //STLPORT_UNIT_TEST_STACK_ALLOCATOR_H
    207