OSDN Git Service

d2759f4653fa812f3a70a6cfecbd84bf95d00118
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / testsuite / util / testsuite_allocator.h
1 // -*- C++ -*-
2 // Testing allocator for the C++ library testsuite.
3 //
4 // Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
5 // Free Software Foundation, Inc.
6 //
7 // This file is part of the GNU ISO C++ Library.  This library is free
8 // software; you can redistribute it and/or modify it under the
9 // terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 3, or (at your option)
11 // any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License along
19 // with this library; see the file COPYING3.  If not see
20 // <http://www.gnu.org/licenses/>.
21 //
22
23 // This file provides an test instrumentation allocator that can be
24 // used to verify allocation functionality of standard library
25 // containers.  2002.11.25 smw
26
27 #ifndef _GLIBCXX_TESTSUITE_ALLOCATOR_H
28 #define _GLIBCXX_TESTSUITE_ALLOCATOR_H
29
30 #include <cstddef>
31 #include <tr1/unordered_map>
32 #include <cassert>
33 #include <bits/move.h>
34
35 namespace 
36 {
37   bool new_called = false;
38   bool delete_called = false;
39 }
40
41 namespace __gnu_test
42 {
43   class tracker_allocator_counter
44   {
45   public:
46     typedef std::size_t    size_type; 
47     
48     static void*
49     allocate(size_type blocksize)
50     {
51       allocationCount_ += blocksize;
52       return ::operator new(blocksize);
53     }
54     
55     static void
56     construct() { constructCount_++; }
57
58     static void
59     destroy() { destructCount_++; }
60
61     static void
62     deallocate(void* p, size_type blocksize)
63     {
64       ::operator delete(p);
65       deallocationCount_ += blocksize;
66     }
67     
68     static size_type
69     get_allocation_count() { return allocationCount_; }
70     
71     static size_type
72     get_deallocation_count() { return deallocationCount_; }
73     
74     static int
75     get_construct_count() { return constructCount_; }
76
77     static int
78     get_destruct_count() { return destructCount_; }
79     
80     static void
81     reset()
82     {
83       allocationCount_ = 0;
84       deallocationCount_ = 0;
85       constructCount_ = 0;
86       destructCount_ = 0;
87     }
88
89  private:
90     static size_type  allocationCount_;
91     static size_type  deallocationCount_;
92     static int        constructCount_;
93     static int        destructCount_;
94   };
95
96   // A simple basic allocator that just forwards to the
97   // tracker_allocator_counter to fulfill memory requests.  This class
98   // is templated on the target object type, but tracker isn't.
99   template<class T>
100   class tracker_allocator
101   {
102   private:
103     typedef tracker_allocator_counter counter_type;
104
105   public:
106     typedef T              value_type;
107     typedef T*             pointer;
108     typedef const T*       const_pointer;
109     typedef T&             reference;
110     typedef const T&       const_reference;
111     typedef std::size_t    size_type; 
112     typedef std::ptrdiff_t difference_type; 
113     
114     template<class U> struct rebind { typedef tracker_allocator<U> other; };
115     
116     pointer
117     address(reference value) const
118     { return &value; }
119     
120     const_pointer
121     address(const_reference value) const
122     { return &value; }
123     
124     tracker_allocator() throw()
125     { }
126
127     tracker_allocator(const tracker_allocator&) throw()
128     { }
129
130     template<class U>
131       tracker_allocator(const tracker_allocator<U>&) throw()
132       { }
133
134     ~tracker_allocator() throw()
135     { }
136
137     size_type
138     max_size() const throw()
139     { return size_type(-1) / sizeof(T); }
140
141     pointer
142     allocate(size_type n, const void* = 0)
143     { return static_cast<pointer>(counter_type::allocate(n * sizeof(T))); }
144
145     void
146     construct(pointer p, const T& value)
147     {
148       ::new ((void *)p) T(value);
149       counter_type::construct();
150     }
151
152 #ifdef __GXX_EXPERIMENTAL_CXX0X__
153       template<typename... Args>
154         void
155         construct(pointer p, Args&&... args) 
156         {
157           ::new((void *)p) T(std::forward<Args>(args)...);
158           counter_type::construct();
159         }
160 #endif
161
162     void
163     destroy(pointer p)
164     {
165       p->~T();
166       counter_type::destroy();
167     }
168
169     void
170     deallocate(pointer p, size_type num)
171     { counter_type::deallocate(p, num * sizeof(T)); }
172   };
173
174   template<class T1, class T2>
175     bool
176     operator==(const tracker_allocator<T1>&, 
177                const tracker_allocator<T2>&) throw()
178     { return true; }
179
180   template<class T1, class T2>
181     bool
182     operator!=(const tracker_allocator<T1>&, 
183                const tracker_allocator<T2>&) throw()
184     { return false; }
185
186   bool
187   check_construct_destroy(const char* tag, int expected_c, int expected_d);
188
189   template<typename Alloc, bool uses_global_new>
190     bool 
191     check_new(Alloc a = Alloc())
192     {
193       bool test __attribute__((unused)) = true;
194       a.allocate(10);
195       test &= ( new_called == uses_global_new );
196       return test;
197     }
198
199   template<typename Alloc, bool uses_global_delete>
200     bool 
201     check_delete(Alloc a = Alloc())
202     {
203       bool test __attribute__((unused)) = true;
204       typename Alloc::pointer p = a.allocate(10);
205       a.deallocate(p, 10);
206       test &= ( delete_called == uses_global_delete );
207       return test;
208     }
209
210   template<typename Alloc>
211     bool
212     check_deallocate_null()
213     {
214       // Let's not core here...
215       Alloc  a;
216       a.deallocate(NULL, 1);
217       a.deallocate(NULL, 10);
218       return true;
219     }
220
221   template<typename Alloc>
222     bool 
223     check_allocate_max_size()
224     {
225       Alloc a;
226       try
227         {
228           a.allocate(a.max_size() + 1);
229         }
230       catch(std::bad_alloc&)
231         {
232           return true;
233         }
234       catch(...)
235         {
236           throw;
237         }
238       throw;
239     }
240
241
242   // A simple allocator which can be constructed endowed of a given
243   // "personality" (an integer), queried in operator== to simulate the
244   // behavior of realworld "unequal" allocators (i.e., not exploiting
245   // the provision in 20.1.5/4, first bullet).  A global unordered_map,
246   // filled at allocation time with (pointer, personality) pairs, is
247   // then consulted to enforce the requirements in Table 32 about
248   // deallocation vs allocator equality.  Note that this allocator is
249   // swappable, not assignable, consistently with Option 3 of DR 431
250   // (see N1599).
251   struct uneq_allocator_base
252   {
253     typedef std::tr1::unordered_map<void*, int>   map_type;
254
255     // Avoid static initialization troubles and/or bad interactions
256     // with tests linking testsuite_allocator.o and playing globally
257     // with operator new/delete.
258     static map_type&
259     get_map()
260     {
261       static map_type alloc_map;
262       return alloc_map;
263     }
264   };
265
266   template<typename Tp>
267     class uneq_allocator
268     : private uneq_allocator_base
269     {
270     public:
271       typedef size_t                              size_type;
272       typedef ptrdiff_t                           difference_type;
273       typedef Tp*                                 pointer;
274       typedef const Tp*                           const_pointer;
275       typedef Tp&                                 reference;
276       typedef const Tp&                           const_reference;
277       typedef Tp                                  value_type;
278       
279       template<typename Tp1>
280         struct rebind
281         { typedef uneq_allocator<Tp1> other; };
282
283       uneq_allocator() throw()
284       : personality(0) { }
285
286       uneq_allocator(int person) throw()
287       : personality(person) { }
288       
289       template<typename Tp1>
290         uneq_allocator(const uneq_allocator<Tp1>& b) throw()
291         : personality(b.get_personality()) { }
292
293       int get_personality() const { return personality; }
294       
295       pointer
296       address(reference x) const { return &x; }
297     
298       const_pointer
299       address(const_reference x) const { return &x; }
300     
301       pointer
302       allocate(size_type n, const void* = 0)
303       { 
304         if (__builtin_expect(n > this->max_size(), false))
305           std::__throw_bad_alloc();
306         
307         pointer p = static_cast<Tp*>(::operator new(n * sizeof(Tp)));
308         try
309           {
310             get_map().insert(map_type::value_type(reinterpret_cast<void*>(p),
311                                                   personality));
312           }
313         catch(...)
314           {
315             ::operator delete(p);
316             __throw_exception_again;
317           }
318         return p;
319       }
320       
321       void
322       deallocate(pointer p, size_type)
323       {
324         assert( p );
325         
326         map_type::iterator it = get_map().find(reinterpret_cast<void*>(p));
327         assert( it != get_map().end() );
328
329         // Enforce requirements in Table 32 about deallocation vs
330         // allocator equality.
331         assert( it->second == personality );
332         
333         get_map().erase(it);
334         ::operator delete(p);
335       }
336       
337       size_type
338       max_size() const throw() 
339       { return size_type(-1) / sizeof(Tp); }
340       
341       void 
342       construct(pointer p, const Tp& val) 
343       { ::new((void *)p) Tp(val); }
344
345 #ifdef __GXX_EXPERIMENTAL_CXX0X__
346       template<typename... Args>
347         void
348         construct(pointer p, Args&&... args) 
349         { ::new((void *)p) Tp(std::forward<Args>(args)...); }
350 #endif
351
352       void 
353       destroy(pointer p) { p->~Tp(); }
354
355     private:
356       // Not assignable...
357       uneq_allocator&
358       operator=(const uneq_allocator&);
359
360       // ... yet swappable!
361       friend inline void
362       swap(uneq_allocator& a, uneq_allocator& b)
363       { std::swap(a.personality, b.personality); } 
364       
365       template<typename Tp1>
366         friend inline bool
367         operator==(const uneq_allocator& a, const uneq_allocator<Tp1>& b)
368         { return a.personality == b.personality; }
369
370       template<typename Tp1>
371         friend inline bool
372         operator!=(const uneq_allocator& a, const uneq_allocator<Tp1>& b)
373         { return !(a == b); }
374       
375       int personality;
376     };
377 } // namespace __gnu_test
378
379 #endif // _GLIBCXX_TESTSUITE_ALLOCATOR_H