test_allocator.h revision 1b92188a82b01e76ac6e8ad5f997293c2a078adc
1#ifndef TEST_ALLOCATOR_H 2#define TEST_ALLOCATOR_H 3 4#include <cstddef> 5#include <type_traits> 6#include <cstdlib> 7#include <new> 8#include <climits> 9#include <cassert> 10 11class test_alloc_base 12{ 13protected: 14 static int time_to_throw; 15public: 16 static int throw_after; 17 static int count; 18 static int alloc_count; 19}; 20 21int test_alloc_base::count = 0; 22int test_alloc_base::time_to_throw = 0; 23int test_alloc_base::alloc_count = 0; 24int test_alloc_base::throw_after = INT_MAX; 25 26template <class T> 27class test_allocator 28 : public test_alloc_base 29{ 30 int data_; 31 32 template <class U> friend class test_allocator; 33public: 34 35 typedef unsigned size_type; 36 typedef int difference_type; 37 typedef T value_type; 38 typedef value_type* pointer; 39 typedef const value_type* const_pointer; 40 typedef typename std::add_lvalue_reference<value_type>::type reference; 41 typedef typename std::add_lvalue_reference<const value_type>::type const_reference; 42 43 template <class U> struct rebind {typedef test_allocator<U> other;}; 44 45 test_allocator() throw() : data_(0) {++count;} 46 explicit test_allocator(int i) throw() : data_(i) {++count;} 47 test_allocator(const test_allocator& a) throw() 48 : data_(a.data_) {++count;} 49 template <class U> test_allocator(const test_allocator<U>& a) throw() 50 : data_(a.data_) {++count;} 51 ~test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;} 52 pointer address(reference x) const {return &x;} 53 const_pointer address(const_reference x) const {return &x;} 54 pointer allocate(size_type n, const void* = 0) 55 { 56 assert(data_ >= 0); 57 if (time_to_throw >= throw_after) { 58#ifndef _LIBCPP_NO_EXCEPTIONS 59 throw std::bad_alloc(); 60#else 61 std::terminate(); 62#endif 63 } 64 ++time_to_throw; 65 ++alloc_count; 66 return (pointer)std::malloc(n * sizeof(T)); 67 } 68 void deallocate(pointer p, size_type n) 69 {assert(data_ >= 0); --alloc_count; std::free(p);} 70 size_type max_size() const throw() 71 {return UINT_MAX / sizeof(T);} 72 void construct(pointer p, const T& val) 73 {::new(p) T(val);} 74#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 75 void construct(pointer p, T&& val) 76 {::new(p) T(std::move(val));} 77#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES 78 void destroy(pointer p) {p->~T();} 79 80 friend bool operator==(const test_allocator& x, const test_allocator& y) 81 {return x.data_ == y.data_;} 82 friend bool operator!=(const test_allocator& x, const test_allocator& y) 83 {return !(x == y);} 84}; 85 86template <> 87class test_allocator<void> 88 : public test_alloc_base 89{ 90 int data_; 91 92 template <class U> friend class test_allocator; 93public: 94 95 typedef unsigned size_type; 96 typedef int difference_type; 97 typedef void value_type; 98 typedef value_type* pointer; 99 typedef const value_type* const_pointer; 100 101 template <class U> struct rebind {typedef test_allocator<U> other;}; 102 103 test_allocator() throw() : data_(-1) {} 104 explicit test_allocator(int i) throw() : data_(i) {} 105 test_allocator(const test_allocator& a) throw() 106 : data_(a.data_) {} 107 template <class U> test_allocator(const test_allocator<U>& a) throw() 108 : data_(a.data_) {} 109 ~test_allocator() throw() {data_ = 0;} 110 111 friend bool operator==(const test_allocator& x, const test_allocator& y) 112 {return x.data_ == y.data_;} 113 friend bool operator!=(const test_allocator& x, const test_allocator& y) 114 {return !(x == y);} 115}; 116 117template <class T> 118class other_allocator 119{ 120 int data_; 121 122 template <class U> friend class other_allocator; 123 124public: 125 typedef T value_type; 126 127 other_allocator() : data_(-1) {} 128 explicit other_allocator(int i) : data_(i) {} 129 template <class U> other_allocator(const other_allocator<U>& a) 130 : data_(a.data_) {} 131 T* allocate(std::size_t n) 132 {return (T*)std::malloc(n * sizeof(T));} 133 void deallocate(T* p, std::size_t n) 134 {std::free(p);} 135 136 other_allocator select_on_container_copy_construction() const 137 {return other_allocator(-2);} 138 139 friend bool operator==(const other_allocator& x, const other_allocator& y) 140 {return x.data_ == y.data_;} 141 friend bool operator!=(const other_allocator& x, const other_allocator& y) 142 {return !(x == y);} 143 144 typedef std::true_type propagate_on_container_copy_assignment; 145 typedef std::true_type propagate_on_container_move_assignment; 146 typedef std::true_type propagate_on_container_swap; 147 148#ifdef _LIBCPP_HAS_NO_ADVANCED_SFINAE 149 std::size_t max_size() const 150 {return UINT_MAX / sizeof(T);} 151#endif // _LIBCPP_HAS_NO_ADVANCED_SFINAE 152 153}; 154 155#endif // TEST_ALLOCATOR_H 156