3 // Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 2, or (at your option) any later
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this library; see the file COPYING. If not, write to
18 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
19 // MA 02111-1307, USA.
21 // As a special exception, you may use this file as part of a free
22 // software library without restriction. Specifically, if other files
23 // instantiate templates or use macros or inline functions from this
24 // file, or you compile this file and link it with other files to
25 // produce an executable, this file does not by itself cause the
26 // resulting executable to be covered by the GNU General Public
27 // License. This exception does not however invalidate any other
28 // reasons why the executable file might be covered by the GNU General
31 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
33 // Permission to use, copy, modify, sell, and distribute this software
34 // is hereby granted without fee, provided that the above copyright
35 // notice appears in all copies, and that both that copyright notice
36 // and this permission notice appear in supporting documentation. None
37 // of the above authors, nor IBM Haifa Research Laboratories, make any
38 // representation about the suitability of this software for any
39 // purpose. It is provided "as is" without express or implied
42 /** @file ext/vstring.h
43 * This file is a GNU extension to the Standard C++ Library.
45 * Contains an exception-throwing allocator, useful for testing
46 * exception safety. In addition, allocation addresses are stored and
51 * @file throw_allocator.h
54 #ifndef _THROW_ALLOCATOR_H
55 #define _THROW_ALLOCATOR_H 1
67 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx
)
69 class twister_rand_gen
72 twister_rand_gen(unsigned int seed
=
73 static_cast<unsigned int>(std::time(0)));
82 std::tr1::mt19937 _M_generator
;
86 struct forced_exception_error
: public std::exception
89 class throw_allocator_base
93 init(unsigned long seed
);
96 set_throw_prob(double throw_prob
);
107 struct group_throw_prob_adjustor
109 group_throw_prob_adjustor(size_t size
)
110 : _M_throw_prob_orig(_S_throw_prob
)
113 1 - std::pow(double(1 - _S_throw_prob
), double(0.5 / (size
+ 1)));
116 ~group_throw_prob_adjustor()
117 { _S_throw_prob
= _M_throw_prob_orig
; }
120 const double _M_throw_prob_orig
;
123 struct zero_throw_prob_adjustor
125 zero_throw_prob_adjustor() : _M_throw_prob_orig(_S_throw_prob
)
126 { _S_throw_prob
= 0; }
128 ~zero_throw_prob_adjustor()
129 { _S_throw_prob
= _M_throw_prob_orig
; }
132 const double _M_throw_prob_orig
;
137 insert(void*, size_t);
140 erase(void*, size_t);
143 throw_conditionally();
145 // See if a particular address and size has been allocated by this
148 check_allocated(void*, size_t);
150 // See if a given label has been allocated by this allocator.
152 check_allocated(size_t);
155 typedef std::pair
<size_t, size_t> alloc_data_type
;
156 typedef std::map
<void*, alloc_data_type
> map_type
;
157 typedef map_type::value_type entry_type
;
158 typedef map_type::const_iterator const_iterator
;
159 typedef map_type::const_reference const_reference
;
162 operator<<(std::ostream
&, const throw_allocator_base
&);
165 make_entry(void*, size_t);
168 print_to_string(std::string
&);
171 print_to_string(std::string
&, const_reference
);
173 static twister_rand_gen _S_g
;
174 static map_type _S_map
;
175 static double _S_throw_prob
;
176 static size_t _S_label
;
181 class throw_allocator
: public throw_allocator_base
184 typedef size_t size_type
;
185 typedef ptrdiff_t difference_type
;
186 typedef T value_type
;
187 typedef value_type
* pointer
;
188 typedef const value_type
* const_pointer
;
189 typedef value_type
& reference
;
190 typedef const value_type
& const_reference
;
196 typedef throw_allocator
<U
> other
;
199 throw_allocator() throw() { }
201 throw_allocator(const throw_allocator
&) throw() { }
204 throw_allocator(const throw_allocator
<U
>&) throw() { }
206 ~throw_allocator() throw() { }
209 max_size() const throw()
210 { return std::allocator
<value_type
>().max_size(); }
213 allocate(size_type num
, std::allocator
<void>::const_pointer hint
= 0)
215 throw_conditionally();
216 value_type
* const a
= std::allocator
<value_type
>().allocate(num
, hint
);
217 insert(a
, sizeof(value_type
) * num
);
222 construct(pointer p
, const T
& val
)
223 { return std::allocator
<value_type
>().construct(p
, val
); }
227 { std::allocator
<value_type
>().destroy(p
); }
230 deallocate(pointer p
, size_type num
)
232 erase(p
, sizeof(value_type
) * num
);
233 std::allocator
<value_type
>().deallocate(p
, num
);
237 check_allocated(pointer p
, size_type num
)
238 { throw_allocator_base::check_allocated(p
, sizeof(value_type
) * num
); }
241 check_allocated(size_type label
)
242 { throw_allocator_base::check_allocated(label
); }
247 operator==(const throw_allocator
<T
>&, const throw_allocator
<T
>&)
252 operator!=(const throw_allocator
<T
>&, const throw_allocator
<T
>&)
256 operator<<(std::ostream
& os
, const throw_allocator_base
& alloc
)
259 throw_allocator_base::print_to_string(error
);
264 // XXX Should be in .cc.
266 twister_rand_gen(unsigned int seed
) : _M_generator(seed
) { }
270 init(unsigned int seed
)
271 { _M_generator
.seed(seed
); }
277 const double eng_min
= _M_generator
.min();
278 const double eng_range
=
279 static_cast<const double>(_M_generator
.max() - eng_min
);
281 const double eng_res
=
282 static_cast<const double>(_M_generator() - eng_min
);
284 const double ret
= eng_res
/ eng_range
;
285 _GLIBCXX_DEBUG_ASSERT(ret
>= 0 && ret
<= 1);
289 twister_rand_gen
throw_allocator_base::_S_g
;
291 throw_allocator_base::map_type
292 throw_allocator_base::_S_map
;
294 double throw_allocator_base::_S_throw_prob
;
296 size_t throw_allocator_base::_S_label
= 0;
298 throw_allocator_base::entry_type
299 throw_allocator_base::make_entry(void* p
, size_t size
)
300 { return std::make_pair(p
, alloc_data_type(_S_label
, size
)); }
303 throw_allocator_base::init(unsigned long seed
)
307 throw_allocator_base::set_throw_prob(double throw_prob
)
308 { _S_throw_prob
= throw_prob
; }
311 throw_allocator_base::get_throw_prob()
312 { return _S_throw_prob
; }
315 throw_allocator_base::set_label(size_t l
)
319 throw_allocator_base::insert(void* p
, size_t size
)
321 const_iterator found_it
= _S_map
.find(p
);
322 if (found_it
!= _S_map
.end())
324 std::string
error("throw_allocator_base::insert");
325 error
+= "double insert!";
327 print_to_string(error
, make_entry(p
, size
));
328 print_to_string(error
, *found_it
);
329 throw std::logic_error(error
);
331 _S_map
.insert(make_entry(p
, size
));
335 throw_allocator_base::empty()
336 { return _S_map
.empty(); }
339 throw_allocator_base::erase(void* p
, size_t size
)
341 check_allocated(p
, size
);
346 throw_allocator_base::check_allocated(void* p
, size_t size
)
348 const_iterator found_it
= _S_map
.find(p
);
349 if (found_it
== _S_map
.end())
351 std::string
error("throw_allocator_base::check_allocated by value ");
352 error
+= "null erase!";
354 print_to_string(error
, make_entry(p
, size
));
355 throw std::logic_error(error
);
358 if (found_it
->second
.second
!= size
)
360 std::string
error("throw_allocator_base::check_allocated by value ");
361 error
+= "wrong-size erase!";
363 print_to_string(error
, make_entry(p
, size
));
364 print_to_string(error
, *found_it
);
365 throw std::logic_error(error
);
370 throw_allocator_base::check_allocated(size_t label
)
373 const_iterator it
= _S_map
.begin();
374 while (it
!= _S_map
.end())
376 if (it
->second
.first
== label
)
377 print_to_string(found
, *it
);
383 std::string
error("throw_allocator_base::check_allocated by label ");
386 throw std::logic_error(error
);
391 throw_allocator_base::throw_conditionally()
393 if (_S_g
.get_prob() < _S_throw_prob
)
394 throw forced_exception_error();
398 throw_allocator_base::print_to_string(std::string
& s
)
400 const_iterator begin
= throw_allocator_base::_S_map
.begin();
401 const_iterator end
= throw_allocator_base::_S_map
.end();
402 for (; begin
!= end
; ++begin
)
403 print_to_string(s
, *begin
);
407 throw_allocator_base::print_to_string(std::string
& s
, const_reference ref
)
410 const char tab('\t');
412 sprintf(buf
, "%p", ref
.first
);
416 sprintf(buf
, "%u", ref
.second
.first
);
420 sprintf(buf
, "%u", ref
.second
.second
);
425 _GLIBCXX_END_NAMESPACE