1f8a1b7d9SAlexander Kabaev // -*- C++ -*-
2f8a1b7d9SAlexander Kabaev 
3f8a1b7d9SAlexander Kabaev // Copyright (C) 2005, 2006 Free Software Foundation, Inc.
4f8a1b7d9SAlexander Kabaev //
5f8a1b7d9SAlexander Kabaev // This file is part of the GNU ISO C++ Library.  This library is free
6f8a1b7d9SAlexander Kabaev // software; you can redistribute it and/or modify it under the terms
7f8a1b7d9SAlexander Kabaev // of the GNU General Public License as published by the Free Software
8f8a1b7d9SAlexander Kabaev // Foundation; either version 2, or (at your option) any later
9f8a1b7d9SAlexander Kabaev // version.
10f8a1b7d9SAlexander Kabaev 
11f8a1b7d9SAlexander Kabaev // This library is distributed in the hope that it will be useful, but
12f8a1b7d9SAlexander Kabaev // WITHOUT ANY WARRANTY; without even the implied warranty of
13f8a1b7d9SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14f8a1b7d9SAlexander Kabaev // General Public License for more details.
15f8a1b7d9SAlexander Kabaev 
16f8a1b7d9SAlexander Kabaev // You should have received a copy of the GNU General Public License
17f8a1b7d9SAlexander Kabaev // along with this library; see the file COPYING.  If not, write to
18f8a1b7d9SAlexander Kabaev // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
19f8a1b7d9SAlexander Kabaev // MA 02111-1307, USA.
20f8a1b7d9SAlexander Kabaev 
21f8a1b7d9SAlexander Kabaev // As a special exception, you may use this file as part of a free
22f8a1b7d9SAlexander Kabaev // software library without restriction.  Specifically, if other files
23f8a1b7d9SAlexander Kabaev // instantiate templates or use macros or inline functions from this
24f8a1b7d9SAlexander Kabaev // file, or you compile this file and link it with other files to
25f8a1b7d9SAlexander Kabaev // produce an executable, this file does not by itself cause the
26f8a1b7d9SAlexander Kabaev // resulting executable to be covered by the GNU General Public
27f8a1b7d9SAlexander Kabaev // License.  This exception does not however invalidate any other
28f8a1b7d9SAlexander Kabaev // reasons why the executable file might be covered by the GNU General
29f8a1b7d9SAlexander Kabaev // Public License.
30f8a1b7d9SAlexander Kabaev 
31f8a1b7d9SAlexander Kabaev // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
32f8a1b7d9SAlexander Kabaev 
33f8a1b7d9SAlexander Kabaev // Permission to use, copy, modify, sell, and distribute this software
34f8a1b7d9SAlexander Kabaev // is hereby granted without fee, provided that the above copyright
35f8a1b7d9SAlexander Kabaev // notice appears in all copies, and that both that copyright notice
36f8a1b7d9SAlexander Kabaev // and this permission notice appear in supporting documentation. None
37f8a1b7d9SAlexander Kabaev // of the above authors, nor IBM Haifa Research Laboratories, make any
38f8a1b7d9SAlexander Kabaev // representation about the suitability of this software for any
39f8a1b7d9SAlexander Kabaev // purpose. It is provided "as is" without express or implied
40f8a1b7d9SAlexander Kabaev // warranty.
41f8a1b7d9SAlexander Kabaev 
42f8a1b7d9SAlexander Kabaev /** @file ext/vstring.h
43f8a1b7d9SAlexander Kabaev  *  This file is a GNU extension to the Standard C++ Library.
44f8a1b7d9SAlexander Kabaev  *
45f8a1b7d9SAlexander Kabaev  *  Contains an exception-throwing allocator, useful for testing
46f8a1b7d9SAlexander Kabaev  *  exception safety. In addition, allocation addresses are stored and
47f8a1b7d9SAlexander Kabaev  *  sanity checked.
48f8a1b7d9SAlexander Kabaev  */
49f8a1b7d9SAlexander Kabaev 
50f8a1b7d9SAlexander Kabaev /**
51f8a1b7d9SAlexander Kabaev  * @file throw_allocator.h
52f8a1b7d9SAlexander Kabaev  */
53f8a1b7d9SAlexander Kabaev 
54f8a1b7d9SAlexander Kabaev #ifndef _THROW_ALLOCATOR_H
55f8a1b7d9SAlexander Kabaev #define _THROW_ALLOCATOR_H 1
56f8a1b7d9SAlexander Kabaev 
57f8a1b7d9SAlexander Kabaev #include <cmath>
58f8a1b7d9SAlexander Kabaev #include <map>
59f8a1b7d9SAlexander Kabaev #include <set>
60f8a1b7d9SAlexander Kabaev #include <string>
61f8a1b7d9SAlexander Kabaev #include <ostream>
62f8a1b7d9SAlexander Kabaev #include <stdexcept>
63f8a1b7d9SAlexander Kabaev #include <utility>
64f8a1b7d9SAlexander Kabaev #include <tr1/random>
650995a43fSAlexander Kabaev #include <bits/functexcept.h>
66f8a1b7d9SAlexander Kabaev 
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)67f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
68f8a1b7d9SAlexander Kabaev 
69f8a1b7d9SAlexander Kabaev   class twister_rand_gen
70f8a1b7d9SAlexander Kabaev   {
71f8a1b7d9SAlexander Kabaev   public:
72f8a1b7d9SAlexander Kabaev     twister_rand_gen(unsigned int seed =
73f8a1b7d9SAlexander Kabaev 		     static_cast<unsigned int>(std::time(0)));
74f8a1b7d9SAlexander Kabaev 
75f8a1b7d9SAlexander Kabaev     void
76f8a1b7d9SAlexander Kabaev     init(unsigned int);
77f8a1b7d9SAlexander Kabaev 
78f8a1b7d9SAlexander Kabaev     double
79f8a1b7d9SAlexander Kabaev     get_prob();
80f8a1b7d9SAlexander Kabaev 
81f8a1b7d9SAlexander Kabaev   private:
82f8a1b7d9SAlexander Kabaev     std::tr1::mt19937 _M_generator;
83f8a1b7d9SAlexander Kabaev   };
84f8a1b7d9SAlexander Kabaev 
85f8a1b7d9SAlexander Kabaev   struct forced_exception_error : public std::exception
86f8a1b7d9SAlexander Kabaev   { };
87f8a1b7d9SAlexander Kabaev 
880995a43fSAlexander Kabaev   // Substitute for concurrence_error object in the case of -fno-exceptions.
890995a43fSAlexander Kabaev   inline void
__throw_forced_exception_error()900995a43fSAlexander Kabaev   __throw_forced_exception_error()
910995a43fSAlexander Kabaev   {
920995a43fSAlexander Kabaev #if __EXCEPTIONS
930995a43fSAlexander Kabaev     throw forced_exception_error();
940995a43fSAlexander Kabaev #else
950995a43fSAlexander Kabaev     __builtin_abort();
960995a43fSAlexander Kabaev #endif
970995a43fSAlexander Kabaev   }
980995a43fSAlexander Kabaev 
99f8a1b7d9SAlexander Kabaev   class throw_allocator_base
100f8a1b7d9SAlexander Kabaev   {
101f8a1b7d9SAlexander Kabaev   public:
102f8a1b7d9SAlexander Kabaev     void
103f8a1b7d9SAlexander Kabaev     init(unsigned long seed);
104f8a1b7d9SAlexander Kabaev 
105f8a1b7d9SAlexander Kabaev     static void
106f8a1b7d9SAlexander Kabaev     set_throw_prob(double throw_prob);
107f8a1b7d9SAlexander Kabaev 
108f8a1b7d9SAlexander Kabaev     static double
109f8a1b7d9SAlexander Kabaev     get_throw_prob();
110f8a1b7d9SAlexander Kabaev 
111f8a1b7d9SAlexander Kabaev     static void
112f8a1b7d9SAlexander Kabaev     set_label(size_t l);
113f8a1b7d9SAlexander Kabaev 
114f8a1b7d9SAlexander Kabaev     static bool
115f8a1b7d9SAlexander Kabaev     empty();
116f8a1b7d9SAlexander Kabaev 
117f8a1b7d9SAlexander Kabaev     struct group_throw_prob_adjustor
118f8a1b7d9SAlexander Kabaev     {
group_throw_prob_adjustorgroup_throw_prob_adjustor119f8a1b7d9SAlexander Kabaev       group_throw_prob_adjustor(size_t size)
120f8a1b7d9SAlexander Kabaev       : _M_throw_prob_orig(_S_throw_prob)
121f8a1b7d9SAlexander Kabaev       {
122f8a1b7d9SAlexander Kabaev 	_S_throw_prob =
123f8a1b7d9SAlexander Kabaev 	  1 - ::pow(double(1 - _S_throw_prob), double(0.5 / (size + 1)));
124f8a1b7d9SAlexander Kabaev       }
125f8a1b7d9SAlexander Kabaev 
~group_throw_prob_adjustorgroup_throw_prob_adjustor126f8a1b7d9SAlexander Kabaev       ~group_throw_prob_adjustor()
127f8a1b7d9SAlexander Kabaev       { _S_throw_prob = _M_throw_prob_orig; }
128f8a1b7d9SAlexander Kabaev 
129f8a1b7d9SAlexander Kabaev     private:
130f8a1b7d9SAlexander Kabaev       const double _M_throw_prob_orig;
131f8a1b7d9SAlexander Kabaev     };
132f8a1b7d9SAlexander Kabaev 
133f8a1b7d9SAlexander Kabaev     struct zero_throw_prob_adjustor
134f8a1b7d9SAlexander Kabaev     {
zero_throw_prob_adjustorzero_throw_prob_adjustor135f8a1b7d9SAlexander Kabaev       zero_throw_prob_adjustor() : _M_throw_prob_orig(_S_throw_prob)
136f8a1b7d9SAlexander Kabaev       { _S_throw_prob = 0; }
137f8a1b7d9SAlexander Kabaev 
~zero_throw_prob_adjustorzero_throw_prob_adjustor138f8a1b7d9SAlexander Kabaev       ~zero_throw_prob_adjustor()
139f8a1b7d9SAlexander Kabaev       { _S_throw_prob = _M_throw_prob_orig; }
140f8a1b7d9SAlexander Kabaev 
141f8a1b7d9SAlexander Kabaev     private:
142f8a1b7d9SAlexander Kabaev       const double _M_throw_prob_orig;
143f8a1b7d9SAlexander Kabaev     };
144f8a1b7d9SAlexander Kabaev 
145f8a1b7d9SAlexander Kabaev   protected:
146f8a1b7d9SAlexander Kabaev     static void
147f8a1b7d9SAlexander Kabaev     insert(void*, size_t);
148f8a1b7d9SAlexander Kabaev 
149f8a1b7d9SAlexander Kabaev     static void
150f8a1b7d9SAlexander Kabaev     erase(void*, size_t);
151f8a1b7d9SAlexander Kabaev 
152f8a1b7d9SAlexander Kabaev     static void
153f8a1b7d9SAlexander Kabaev     throw_conditionally();
154f8a1b7d9SAlexander Kabaev 
155f8a1b7d9SAlexander Kabaev     // See if a particular address and size has been allocated by this
156f8a1b7d9SAlexander Kabaev     // allocator.
157f8a1b7d9SAlexander Kabaev     static void
158f8a1b7d9SAlexander Kabaev     check_allocated(void*, size_t);
159f8a1b7d9SAlexander Kabaev 
160f8a1b7d9SAlexander Kabaev     // See if a given label has been allocated by this allocator.
161f8a1b7d9SAlexander Kabaev     static void
162f8a1b7d9SAlexander Kabaev     check_allocated(size_t);
163f8a1b7d9SAlexander Kabaev 
164f8a1b7d9SAlexander Kabaev   private:
165f8a1b7d9SAlexander Kabaev     typedef std::pair<size_t, size_t> 		alloc_data_type;
166f8a1b7d9SAlexander Kabaev     typedef std::map<void*, alloc_data_type> 	map_type;
167f8a1b7d9SAlexander Kabaev     typedef map_type::value_type 		entry_type;
168f8a1b7d9SAlexander Kabaev     typedef map_type::const_iterator 		const_iterator;
169f8a1b7d9SAlexander Kabaev     typedef map_type::const_reference 		const_reference;
170f8a1b7d9SAlexander Kabaev 
171f8a1b7d9SAlexander Kabaev     friend std::ostream&
172f8a1b7d9SAlexander Kabaev     operator<<(std::ostream&, const throw_allocator_base&);
173f8a1b7d9SAlexander Kabaev 
174f8a1b7d9SAlexander Kabaev     static entry_type
175f8a1b7d9SAlexander Kabaev     make_entry(void*, size_t);
176f8a1b7d9SAlexander Kabaev 
177f8a1b7d9SAlexander Kabaev     static void
178f8a1b7d9SAlexander Kabaev     print_to_string(std::string&);
179f8a1b7d9SAlexander Kabaev 
180f8a1b7d9SAlexander Kabaev     static void
181f8a1b7d9SAlexander Kabaev     print_to_string(std::string&, const_reference);
182f8a1b7d9SAlexander Kabaev 
183f8a1b7d9SAlexander Kabaev     static twister_rand_gen 	_S_g;
184f8a1b7d9SAlexander Kabaev     static map_type 		_S_map;
185f8a1b7d9SAlexander Kabaev     static double 		_S_throw_prob;
186f8a1b7d9SAlexander Kabaev     static size_t 		_S_label;
187f8a1b7d9SAlexander Kabaev   };
188f8a1b7d9SAlexander Kabaev 
189f8a1b7d9SAlexander Kabaev 
190f8a1b7d9SAlexander Kabaev   template<typename T>
191f8a1b7d9SAlexander Kabaev     class throw_allocator : public throw_allocator_base
192f8a1b7d9SAlexander Kabaev     {
193f8a1b7d9SAlexander Kabaev     public:
194f8a1b7d9SAlexander Kabaev       typedef size_t 				size_type;
195f8a1b7d9SAlexander Kabaev       typedef ptrdiff_t 			difference_type;
196f8a1b7d9SAlexander Kabaev       typedef T 				value_type;
197f8a1b7d9SAlexander Kabaev       typedef value_type* 			pointer;
198f8a1b7d9SAlexander Kabaev       typedef const value_type* 		const_pointer;
199f8a1b7d9SAlexander Kabaev       typedef value_type& 			reference;
200f8a1b7d9SAlexander Kabaev       typedef const value_type& 		const_reference;
201f8a1b7d9SAlexander Kabaev 
202f8a1b7d9SAlexander Kabaev 
203f8a1b7d9SAlexander Kabaev       template<typename U>
204f8a1b7d9SAlexander Kabaev       struct rebind
205f8a1b7d9SAlexander Kabaev       {
206f8a1b7d9SAlexander Kabaev         typedef throw_allocator<U> other;
207f8a1b7d9SAlexander Kabaev       };
208f8a1b7d9SAlexander Kabaev 
throw()209f8a1b7d9SAlexander Kabaev       throw_allocator() throw() { }
210f8a1b7d9SAlexander Kabaev 
throw()211f8a1b7d9SAlexander Kabaev       throw_allocator(const throw_allocator&) throw() { }
212f8a1b7d9SAlexander Kabaev 
213f8a1b7d9SAlexander Kabaev       template<typename U>
throw_allocator(const throw_allocator<U> &)214f8a1b7d9SAlexander Kabaev       throw_allocator(const throw_allocator<U>&) throw() { }
215f8a1b7d9SAlexander Kabaev 
throw()216f8a1b7d9SAlexander Kabaev       ~throw_allocator() throw() { }
217f8a1b7d9SAlexander Kabaev 
218f8a1b7d9SAlexander Kabaev       size_type
max_size()219f8a1b7d9SAlexander Kabaev       max_size() const throw()
220f8a1b7d9SAlexander Kabaev       { return std::allocator<value_type>().max_size(); }
221f8a1b7d9SAlexander Kabaev 
222f8a1b7d9SAlexander Kabaev       pointer
223f8a1b7d9SAlexander Kabaev       allocate(size_type num, std::allocator<void>::const_pointer hint = 0)
224f8a1b7d9SAlexander Kabaev       {
225f8a1b7d9SAlexander Kabaev 	throw_conditionally();
226f8a1b7d9SAlexander Kabaev 	value_type* const a = std::allocator<value_type>().allocate(num, hint);
227f8a1b7d9SAlexander Kabaev 	insert(a, sizeof(value_type) * num);
228f8a1b7d9SAlexander Kabaev 	return a;
229f8a1b7d9SAlexander Kabaev       }
230f8a1b7d9SAlexander Kabaev 
231f8a1b7d9SAlexander Kabaev       void
construct(pointer p,const T & val)232f8a1b7d9SAlexander Kabaev       construct(pointer p, const T& val)
233f8a1b7d9SAlexander Kabaev       { return std::allocator<value_type>().construct(p, val); }
234f8a1b7d9SAlexander Kabaev 
235f8a1b7d9SAlexander Kabaev       void
destroy(pointer p)236f8a1b7d9SAlexander Kabaev       destroy(pointer p)
237f8a1b7d9SAlexander Kabaev       { std::allocator<value_type>().destroy(p); }
238f8a1b7d9SAlexander Kabaev 
239f8a1b7d9SAlexander Kabaev       void
deallocate(pointer p,size_type num)240f8a1b7d9SAlexander Kabaev       deallocate(pointer p, size_type num)
241f8a1b7d9SAlexander Kabaev       {
242f8a1b7d9SAlexander Kabaev 	erase(p, sizeof(value_type) * num);
243f8a1b7d9SAlexander Kabaev 	std::allocator<value_type>().deallocate(p, num);
244f8a1b7d9SAlexander Kabaev       }
245f8a1b7d9SAlexander Kabaev 
246f8a1b7d9SAlexander Kabaev       void
check_allocated(pointer p,size_type num)247f8a1b7d9SAlexander Kabaev       check_allocated(pointer p, size_type num)
248f8a1b7d9SAlexander Kabaev       { throw_allocator_base::check_allocated(p, sizeof(value_type) * num); }
249f8a1b7d9SAlexander Kabaev 
250f8a1b7d9SAlexander Kabaev       void
check_allocated(size_type label)251f8a1b7d9SAlexander Kabaev       check_allocated(size_type label)
252f8a1b7d9SAlexander Kabaev       { throw_allocator_base::check_allocated(label); }
253f8a1b7d9SAlexander Kabaev     };
254f8a1b7d9SAlexander Kabaev 
255f8a1b7d9SAlexander Kabaev   template<typename T>
256f8a1b7d9SAlexander Kabaev     inline bool
257f8a1b7d9SAlexander Kabaev     operator==(const throw_allocator<T>&, const throw_allocator<T>&)
258f8a1b7d9SAlexander Kabaev     { return true; }
259f8a1b7d9SAlexander Kabaev 
260f8a1b7d9SAlexander Kabaev   template<typename T>
261f8a1b7d9SAlexander Kabaev     inline bool
262f8a1b7d9SAlexander Kabaev     operator!=(const throw_allocator<T>&, const throw_allocator<T>&)
263f8a1b7d9SAlexander Kabaev     { return false; }
264f8a1b7d9SAlexander Kabaev 
265f8a1b7d9SAlexander Kabaev   std::ostream&
266f8a1b7d9SAlexander Kabaev   operator<<(std::ostream& os, const throw_allocator_base& alloc)
267f8a1b7d9SAlexander Kabaev   {
268f8a1b7d9SAlexander Kabaev     std::string error;
269f8a1b7d9SAlexander Kabaev     throw_allocator_base::print_to_string(error);
270f8a1b7d9SAlexander Kabaev     os << error;
271f8a1b7d9SAlexander Kabaev     return os;
272f8a1b7d9SAlexander Kabaev   }
273f8a1b7d9SAlexander Kabaev 
274f8a1b7d9SAlexander Kabaev   // XXX Should be in .cc.
275f8a1b7d9SAlexander Kabaev   twister_rand_gen::
twister_rand_gen(unsigned int seed)276f8a1b7d9SAlexander Kabaev   twister_rand_gen(unsigned int seed) : _M_generator(seed)  { }
277f8a1b7d9SAlexander Kabaev 
278f8a1b7d9SAlexander Kabaev   void
279f8a1b7d9SAlexander Kabaev   twister_rand_gen::
init(unsigned int seed)280f8a1b7d9SAlexander Kabaev   init(unsigned int seed)
281f8a1b7d9SAlexander Kabaev   { _M_generator.seed(seed); }
282f8a1b7d9SAlexander Kabaev 
283f8a1b7d9SAlexander Kabaev   double
284f8a1b7d9SAlexander Kabaev   twister_rand_gen::
get_prob()285f8a1b7d9SAlexander Kabaev   get_prob()
286f8a1b7d9SAlexander Kabaev   {
287f8a1b7d9SAlexander Kabaev     const double eng_min = _M_generator.min();
288f8a1b7d9SAlexander Kabaev     const double eng_range =
289f8a1b7d9SAlexander Kabaev       static_cast<const double>(_M_generator.max() - eng_min);
290f8a1b7d9SAlexander Kabaev 
291f8a1b7d9SAlexander Kabaev     const double eng_res =
292f8a1b7d9SAlexander Kabaev       static_cast<const double>(_M_generator() - eng_min);
293f8a1b7d9SAlexander Kabaev 
294f8a1b7d9SAlexander Kabaev     const double ret = eng_res / eng_range;
295f8a1b7d9SAlexander Kabaev     _GLIBCXX_DEBUG_ASSERT(ret >= 0 && ret <= 1);
296f8a1b7d9SAlexander Kabaev     return ret;
297f8a1b7d9SAlexander Kabaev   }
298f8a1b7d9SAlexander Kabaev 
299f8a1b7d9SAlexander Kabaev   twister_rand_gen throw_allocator_base::_S_g;
300f8a1b7d9SAlexander Kabaev 
301f8a1b7d9SAlexander Kabaev   throw_allocator_base::map_type
302f8a1b7d9SAlexander Kabaev   throw_allocator_base::_S_map;
303f8a1b7d9SAlexander Kabaev 
304f8a1b7d9SAlexander Kabaev   double throw_allocator_base::_S_throw_prob;
305f8a1b7d9SAlexander Kabaev 
306f8a1b7d9SAlexander Kabaev   size_t throw_allocator_base::_S_label = 0;
307f8a1b7d9SAlexander Kabaev 
308f8a1b7d9SAlexander Kabaev   throw_allocator_base::entry_type
make_entry(void * p,size_t size)309f8a1b7d9SAlexander Kabaev   throw_allocator_base::make_entry(void* p, size_t size)
310f8a1b7d9SAlexander Kabaev   { return std::make_pair(p, alloc_data_type(_S_label, size)); }
311f8a1b7d9SAlexander Kabaev 
312f8a1b7d9SAlexander Kabaev   void
init(unsigned long seed)313f8a1b7d9SAlexander Kabaev   throw_allocator_base::init(unsigned long seed)
314f8a1b7d9SAlexander Kabaev   { _S_g.init(seed); }
315f8a1b7d9SAlexander Kabaev 
316f8a1b7d9SAlexander Kabaev   void
set_throw_prob(double throw_prob)317f8a1b7d9SAlexander Kabaev   throw_allocator_base::set_throw_prob(double throw_prob)
318f8a1b7d9SAlexander Kabaev   { _S_throw_prob = throw_prob; }
319f8a1b7d9SAlexander Kabaev 
320f8a1b7d9SAlexander Kabaev   double
get_throw_prob()321f8a1b7d9SAlexander Kabaev   throw_allocator_base::get_throw_prob()
322f8a1b7d9SAlexander Kabaev   { return _S_throw_prob; }
323f8a1b7d9SAlexander Kabaev 
324f8a1b7d9SAlexander Kabaev   void
set_label(size_t l)325f8a1b7d9SAlexander Kabaev   throw_allocator_base::set_label(size_t l)
326f8a1b7d9SAlexander Kabaev   { _S_label = l; }
327f8a1b7d9SAlexander Kabaev 
328f8a1b7d9SAlexander Kabaev   void
insert(void * p,size_t size)329f8a1b7d9SAlexander Kabaev   throw_allocator_base::insert(void* p, size_t size)
330f8a1b7d9SAlexander Kabaev   {
331f8a1b7d9SAlexander Kabaev     const_iterator found_it = _S_map.find(p);
332f8a1b7d9SAlexander Kabaev     if (found_it != _S_map.end())
333f8a1b7d9SAlexander Kabaev       {
334f8a1b7d9SAlexander Kabaev 	std::string error("throw_allocator_base::insert");
335f8a1b7d9SAlexander Kabaev 	error += "double insert!";
336f8a1b7d9SAlexander Kabaev 	error += '\n';
337f8a1b7d9SAlexander Kabaev 	print_to_string(error, make_entry(p, size));
338f8a1b7d9SAlexander Kabaev 	print_to_string(error, *found_it);
3390995a43fSAlexander Kabaev 	std::__throw_logic_error(error.c_str());
340f8a1b7d9SAlexander Kabaev       }
341f8a1b7d9SAlexander Kabaev     _S_map.insert(make_entry(p, size));
342f8a1b7d9SAlexander Kabaev   }
343f8a1b7d9SAlexander Kabaev 
344f8a1b7d9SAlexander Kabaev   bool
empty()345f8a1b7d9SAlexander Kabaev   throw_allocator_base::empty()
346f8a1b7d9SAlexander Kabaev   { return _S_map.empty(); }
347f8a1b7d9SAlexander Kabaev 
348f8a1b7d9SAlexander Kabaev   void
erase(void * p,size_t size)349f8a1b7d9SAlexander Kabaev   throw_allocator_base::erase(void* p, size_t size)
350f8a1b7d9SAlexander Kabaev   {
351f8a1b7d9SAlexander Kabaev     check_allocated(p, size);
352f8a1b7d9SAlexander Kabaev     _S_map.erase(p);
353f8a1b7d9SAlexander Kabaev   }
354f8a1b7d9SAlexander Kabaev 
355f8a1b7d9SAlexander Kabaev   void
check_allocated(void * p,size_t size)356f8a1b7d9SAlexander Kabaev   throw_allocator_base::check_allocated(void* p, size_t size)
357f8a1b7d9SAlexander Kabaev   {
358f8a1b7d9SAlexander Kabaev     const_iterator found_it = _S_map.find(p);
359f8a1b7d9SAlexander Kabaev     if (found_it == _S_map.end())
360f8a1b7d9SAlexander Kabaev       {
361f8a1b7d9SAlexander Kabaev 	std::string error("throw_allocator_base::check_allocated by value ");
362f8a1b7d9SAlexander Kabaev 	error += "null erase!";
363f8a1b7d9SAlexander Kabaev 	error += '\n';
364f8a1b7d9SAlexander Kabaev 	print_to_string(error, make_entry(p, size));
3650995a43fSAlexander Kabaev 	std::__throw_logic_error(error.c_str());
366f8a1b7d9SAlexander Kabaev       }
367f8a1b7d9SAlexander Kabaev 
368f8a1b7d9SAlexander Kabaev     if (found_it->second.second != size)
369f8a1b7d9SAlexander Kabaev       {
370f8a1b7d9SAlexander Kabaev 	std::string error("throw_allocator_base::check_allocated by value ");
371f8a1b7d9SAlexander Kabaev 	error += "wrong-size erase!";
372f8a1b7d9SAlexander Kabaev 	error += '\n';
373f8a1b7d9SAlexander Kabaev 	print_to_string(error, make_entry(p, size));
374f8a1b7d9SAlexander Kabaev 	print_to_string(error, *found_it);
3750995a43fSAlexander Kabaev 	std::__throw_logic_error(error.c_str());
376f8a1b7d9SAlexander Kabaev       }
377f8a1b7d9SAlexander Kabaev   }
378f8a1b7d9SAlexander Kabaev 
379f8a1b7d9SAlexander Kabaev   void
check_allocated(size_t label)380f8a1b7d9SAlexander Kabaev   throw_allocator_base::check_allocated(size_t label)
381f8a1b7d9SAlexander Kabaev   {
382f8a1b7d9SAlexander Kabaev     std::string found;
383f8a1b7d9SAlexander Kabaev     const_iterator it = _S_map.begin();
384f8a1b7d9SAlexander Kabaev     while (it != _S_map.end())
385f8a1b7d9SAlexander Kabaev       {
386f8a1b7d9SAlexander Kabaev 	if (it->second.first == label)
387f8a1b7d9SAlexander Kabaev 	  print_to_string(found, *it);
388f8a1b7d9SAlexander Kabaev 	++it;
389f8a1b7d9SAlexander Kabaev       }
390f8a1b7d9SAlexander Kabaev 
391f8a1b7d9SAlexander Kabaev     if (!found.empty())
392f8a1b7d9SAlexander Kabaev       {
393f8a1b7d9SAlexander Kabaev 	std::string error("throw_allocator_base::check_allocated by label ");
394f8a1b7d9SAlexander Kabaev 	error += '\n';
395f8a1b7d9SAlexander Kabaev 	error += found;
3960995a43fSAlexander Kabaev 	std::__throw_logic_error(error.c_str());
397f8a1b7d9SAlexander Kabaev       }
398f8a1b7d9SAlexander Kabaev   }
399f8a1b7d9SAlexander Kabaev 
400f8a1b7d9SAlexander Kabaev   void
throw_conditionally()401f8a1b7d9SAlexander Kabaev   throw_allocator_base::throw_conditionally()
402f8a1b7d9SAlexander Kabaev   {
403f8a1b7d9SAlexander Kabaev     if (_S_g.get_prob() < _S_throw_prob)
4040995a43fSAlexander Kabaev       __throw_forced_exception_error();
405f8a1b7d9SAlexander Kabaev   }
406f8a1b7d9SAlexander Kabaev 
407f8a1b7d9SAlexander Kabaev   void
print_to_string(std::string & s)408f8a1b7d9SAlexander Kabaev   throw_allocator_base::print_to_string(std::string& s)
409f8a1b7d9SAlexander Kabaev   {
410f8a1b7d9SAlexander Kabaev     const_iterator begin = throw_allocator_base::_S_map.begin();
411f8a1b7d9SAlexander Kabaev     const_iterator end = throw_allocator_base::_S_map.end();
412f8a1b7d9SAlexander Kabaev     for (; begin != end; ++begin)
413f8a1b7d9SAlexander Kabaev       print_to_string(s, *begin);
414f8a1b7d9SAlexander Kabaev   }
415f8a1b7d9SAlexander Kabaev 
416f8a1b7d9SAlexander Kabaev   void
print_to_string(std::string & s,const_reference ref)417f8a1b7d9SAlexander Kabaev   throw_allocator_base::print_to_string(std::string& s, const_reference ref)
418f8a1b7d9SAlexander Kabaev   {
419f8a1b7d9SAlexander Kabaev     char buf[40];
420f8a1b7d9SAlexander Kabaev     const char tab('\t');
421f8a1b7d9SAlexander Kabaev     s += "address: ";
422f8a1b7d9SAlexander Kabaev     sprintf(buf, "%p", ref.first);
423f8a1b7d9SAlexander Kabaev     s += buf;
424f8a1b7d9SAlexander Kabaev     s += tab;
425f8a1b7d9SAlexander Kabaev     s += "label: ";
426*096464d3SPedro F. Giffuni     sprintf(buf, "%lu", ref.second.first);
427f8a1b7d9SAlexander Kabaev     s += buf;
428f8a1b7d9SAlexander Kabaev     s += tab;
429f8a1b7d9SAlexander Kabaev     s += "size: ";
430*096464d3SPedro F. Giffuni     sprintf(buf, "%lu", ref.second.second);
431f8a1b7d9SAlexander Kabaev     s += buf;
432f8a1b7d9SAlexander Kabaev     s += '\n';
433f8a1b7d9SAlexander Kabaev   }
434f8a1b7d9SAlexander Kabaev 
435f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NAMESPACE
436f8a1b7d9SAlexander Kabaev 
437f8a1b7d9SAlexander Kabaev #endif
438