Home | History | Annotate | Download | only in support
      1 //===----------------------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef TEST_ALLOCATOR_H
     11 #define TEST_ALLOCATOR_H
     12 
     13 #include <cstddef>
     14 #include <type_traits>
     15 #include <cstdlib>
     16 #include <new>
     17 #include <climits>
     18 #include <cassert>
     19 
     20 #include "test_macros.h"
     21 
     22 class test_alloc_base
     23 {
     24 protected:
     25     static int time_to_throw;
     26 public:
     27     static int throw_after;
     28     static int count;
     29     static int alloc_count;
     30 };
     31 
     32 int test_alloc_base::count = 0;
     33 int test_alloc_base::time_to_throw = 0;
     34 int test_alloc_base::alloc_count = 0;
     35 int test_alloc_base::throw_after = INT_MAX;
     36 
     37 template <class T>
     38 class test_allocator
     39     : public test_alloc_base
     40 {
     41     int data_;
     42 
     43     template <class U> friend class test_allocator;
     44 public:
     45 
     46     typedef unsigned                                                   size_type;
     47     typedef int                                                        difference_type;
     48     typedef T                                                          value_type;
     49     typedef value_type*                                                pointer;
     50     typedef const value_type*                                          const_pointer;
     51     typedef typename std::add_lvalue_reference<value_type>::type       reference;
     52     typedef typename std::add_lvalue_reference<const value_type>::type const_reference;
     53 
     54     template <class U> struct rebind {typedef test_allocator<U> other;};
     55 
     56     test_allocator() throw() : data_(0) {++count;}
     57     explicit test_allocator(int i) throw() : data_(i) {++count;}
     58     test_allocator(const test_allocator& a) throw()
     59         : data_(a.data_) {++count;}
     60     template <class U> test_allocator(const test_allocator<U>& a) throw()
     61         : data_(a.data_) {++count;}
     62     ~test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;}
     63     pointer address(reference x) const {return &x;}
     64     const_pointer address(const_reference x) const {return &x;}
     65     pointer allocate(size_type n, const void* = 0)
     66         {
     67             assert(data_ >= 0);
     68             if (time_to_throw >= throw_after) {
     69 #ifndef _LIBCPP_NO_EXCEPTIONS
     70                 throw std::bad_alloc();
     71 #else
     72                 std::terminate();
     73 #endif
     74             }
     75             ++time_to_throw;
     76             ++alloc_count;
     77             return (pointer)::operator new(n * sizeof(T));
     78         }
     79     void deallocate(pointer p, size_type)
     80         {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p);}
     81     size_type max_size() const throw()
     82         {return UINT_MAX / sizeof(T);}
     83     void construct(pointer p, const T& val)
     84         {::new(p) T(val);}
     85 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     86     void construct(pointer p, T&& val)
     87         {::new(p) T(std::move(val));}
     88 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
     89     void destroy(pointer p) {p->~T();}
     90 
     91     friend bool operator==(const test_allocator& x, const test_allocator& y)
     92         {return x.data_ == y.data_;}
     93     friend bool operator!=(const test_allocator& x, const test_allocator& y)
     94         {return !(x == y);}
     95 };
     96 
     97 template <class T>
     98 class non_default_test_allocator
     99     : public test_alloc_base
    100 {
    101     int data_;
    102 
    103     template <class U> friend class non_default_test_allocator;
    104 public:
    105 
    106     typedef unsigned                                                   size_type;
    107     typedef int                                                        difference_type;
    108     typedef T                                                          value_type;
    109     typedef value_type*                                                pointer;
    110     typedef const value_type*                                          const_pointer;
    111     typedef typename std::add_lvalue_reference<value_type>::type       reference;
    112     typedef typename std::add_lvalue_reference<const value_type>::type const_reference;
    113 
    114     template <class U> struct rebind {typedef non_default_test_allocator<U> other;};
    115 
    116 //    non_default_test_allocator() throw() : data_(0) {++count;}
    117     explicit non_default_test_allocator(int i) throw() : data_(i) {++count;}
    118     non_default_test_allocator(const non_default_test_allocator& a) throw()
    119         : data_(a.data_) {++count;}
    120     template <class U> non_default_test_allocator(const non_default_test_allocator<U>& a) throw()
    121         : data_(a.data_) {++count;}
    122     ~non_default_test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;}
    123     pointer address(reference x) const {return &x;}
    124     const_pointer address(const_reference x) const {return &x;}
    125     pointer allocate(size_type n, const void* = 0)
    126         {
    127             assert(data_ >= 0);
    128             if (time_to_throw >= throw_after) {
    129 #ifndef _LIBCPP_NO_EXCEPTIONS
    130                 throw std::bad_alloc();
    131 #else
    132                 std::terminate();
    133 #endif
    134             }
    135             ++time_to_throw;
    136             ++alloc_count;
    137             return (pointer)::operator new (n * sizeof(T));
    138         }
    139     void deallocate(pointer p, size_type)
    140         {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p); }
    141     size_type max_size() const throw()
    142         {return UINT_MAX / sizeof(T);}
    143     void construct(pointer p, const T& val)
    144         {::new(p) T(val);}
    145 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
    146     void construct(pointer p, T&& val)
    147         {::new(p) T(std::move(val));}
    148 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
    149     void destroy(pointer p) {p->~T();}
    150 
    151     friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y)
    152         {return x.data_ == y.data_;}
    153     friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y)
    154         {return !(x == y);}
    155 };
    156 
    157 template <>
    158 class test_allocator<void>
    159     : public test_alloc_base
    160 {
    161     int data_;
    162 
    163     template <class U> friend class test_allocator;
    164 public:
    165 
    166     typedef unsigned                                                   size_type;
    167     typedef int                                                        difference_type;
    168     typedef void                                                       value_type;
    169     typedef value_type*                                                pointer;
    170     typedef const value_type*                                          const_pointer;
    171 
    172     template <class U> struct rebind {typedef test_allocator<U> other;};
    173 
    174     test_allocator() throw() : data_(0) {}
    175     explicit test_allocator(int i) throw() : data_(i) {}
    176     test_allocator(const test_allocator& a) throw()
    177         : data_(a.data_) {}
    178     template <class U> test_allocator(const test_allocator<U>& a) throw()
    179         : data_(a.data_) {}
    180     ~test_allocator() throw() {data_ = -1;}
    181 
    182     friend bool operator==(const test_allocator& x, const test_allocator& y)
    183         {return x.data_ == y.data_;}
    184     friend bool operator!=(const test_allocator& x, const test_allocator& y)
    185         {return !(x == y);}
    186 };
    187 
    188 template <class T>
    189 class other_allocator
    190 {
    191     int data_;
    192 
    193     template <class U> friend class other_allocator;
    194 
    195 public:
    196     typedef T value_type;
    197 
    198     other_allocator() : data_(-1) {}
    199     explicit other_allocator(int i) : data_(i) {}
    200     template <class U> other_allocator(const other_allocator<U>& a)
    201         : data_(a.data_) {}
    202     T* allocate(std::size_t n)
    203         {return (T*)::operator new(n * sizeof(T));}
    204     void deallocate(T* p, std::size_t)
    205         {::operator delete((void*)p);}
    206 
    207     other_allocator select_on_container_copy_construction() const
    208         {return other_allocator(-2);}
    209 
    210     friend bool operator==(const other_allocator& x, const other_allocator& y)
    211         {return x.data_ == y.data_;}
    212     friend bool operator!=(const other_allocator& x, const other_allocator& y)
    213         {return !(x == y);}
    214 
    215     typedef std::true_type propagate_on_container_copy_assignment;
    216     typedef std::true_type propagate_on_container_move_assignment;
    217     typedef std::true_type propagate_on_container_swap;
    218 
    219 #ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE
    220     std::size_t max_size() const
    221         {return UINT_MAX / sizeof(T);}
    222 #endif  // _LIBCPP_HAS_NO_ADVANCED_SFINAE
    223 
    224 };
    225 
    226 #endif  // TEST_ALLOCATOR_H
    227