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