111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// -*- C++ -*- 211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Copyright (C) 2005-2014 Free Software Foundation, Inc. 411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This file is part of the GNU ISO C++ Library. This library is free 611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// software; you can redistribute it and/or modify it under the terms 711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// of the GNU General Public License as published by the Free Software 811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Foundation; either version 3, or (at your option) any later 911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// version. 1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This library is distributed in the hope that it will be useful, but 1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// WITHOUT ANY WARRANTY; without even the implied warranty of 1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// General Public License for more details. 1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Under Section 7 of GPL version 3, you are granted additional 1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// permissions described in the GCC Runtime Library Exception, version 1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 3.1, as published by the Free Software Foundation. 1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// You should have received a copy of the GNU General Public License and 2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// a copy of the GCC Runtime Library Exception along with this program; 2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// <http://www.gnu.org/licenses/>. 2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. 2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Permission to use, copy, modify, sell, and distribute this software 2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// is hereby granted without fee, provided that the above copyright 2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// notice appears in all copies, and that both that copyright notice 3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// and this permission notice appear in supporting documentation. None 3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// of the above authors, nor IBM Haifa Research Laboratories, make any 3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// representation about the suitability of this software for any 3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// purpose. It is provided "as is" without express or implied 3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// warranty. 3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/** @file ext/throw_allocator.h 3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * This file is a GNU extension to the Standard C++ Library. 3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Contains two exception-generating types (throw_value, throw_allocator) 4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * intended to be used as value and allocator types while testing 4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * exception safety in templatized containers and algorithms. The 4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * allocator has additional log and debug features. The exception 4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * generated is of type forced_exception_error. 4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifndef _THROW_ALLOCATOR_H 4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define _THROW_ALLOCATOR_H 1 4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <cmath> 5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <ctime> 5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <map> 5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <string> 5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <ostream> 5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdexcept> 5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <utility> 5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <bits/functexcept.h> 5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <bits/move.h> 5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# include <functional> 6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# include <random> 6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else 6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# include <tr1/functional> 6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# include <tr1/random> 6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertnamespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{ 6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_GLIBCXX_BEGIN_NAMESPACE_VERSION 6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /** 7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * @brief Thown by exception safety machinery. 7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * @ingroup exceptions 7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct forced_error : public std::exception 7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { }; 7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Substitute for forced_error object when -fno-exceptions. 7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline void 7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __throw_forced_error() 8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { _GLIBCXX_THROW_OR_ABORT(forced_error()); } 8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /** 8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * @brief Base class for checking address and label information 8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * about allocations. Create a std::map between the allocated 8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * address (void*) and a datum for annotations, which are a pair of 8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * numbers corresponding to label and allocated size. 8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct annotate_base 8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert annotate_base() 9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert label(); 9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert map_alloc(); 9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void 9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_label(size_t l) 9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { label() = l; } 9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static size_t 10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert get_label() 10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { return label(); } 10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert insert(void* p, size_t size) 10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!p) 10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::insert null insert!\n"); 11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(error, make_entry(p, size)); 11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const_iterator found = map_alloc().find(p); 11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (found != map_alloc().end()) 11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::insert double insert!\n"); 11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(error, make_entry(p, size)); 11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(error, *found); 12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert map_alloc().insert(make_entry(p, size)); 12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert erase(void* p, size_t size) 12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert check_allocated(p, size); 13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert map_alloc().erase(p); 13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert insert_construct(void* p) 13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!p) 13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::insert_construct null!\n"); 14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto found = map_construct().find(p); 14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (found != map_construct().end()) 14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::insert_construct double insert!\n"); 14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(error, std::make_pair(p, get_label())); 14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(error, *found); 14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert map_construct().insert(std::make_pair(p, get_label())); 15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert erase_construct(void* p) 15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert check_constructed(p); 15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert map_construct().erase(p); 16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // See if a particular address and allocation size has been saved. 16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline void 16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert check_allocated(void* p, size_t size) 16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const_iterator found = map_alloc().find(p); 16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (found == map_alloc().end()) 16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::check_allocated by value " 17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "null erase!\n"); 17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(error, make_entry(p, size)); 17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (found->second.second != size) 17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::check_allocated by value " 17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "wrong-size erase!\n"); 18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(error, make_entry(p, size)); 18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(error, *found); 18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // See if a given label has been allocated. 18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline void 18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert check(size_t label) 18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string found; 19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const_iterator beg = map_alloc().begin(); 19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const_iterator end = map_alloc().end(); 19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (beg != end) 19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (beg->second.first == label) 19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(found, *beg); 19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++beg; 19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto beg = map_construct().begin(); 20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto end = map_construct().end(); 20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (beg != end) 20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (beg->second == label) 20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(found, *beg); 21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++beg; 21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!found.empty()) 21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 21711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::check by label\n"); 21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert error += found; 21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // See if there is anything left allocated or constructed. 22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline static void 22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert check() 22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string found; 22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const_iterator beg = map_alloc().begin(); 23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const_iterator end = map_alloc().end(); 23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (beg != end) 23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(found, *beg); 23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++beg; 23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto beg = map_construct().begin(); 24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto end = map_construct().end(); 24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (beg != end) 24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(found, *beg); 24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++beg; 24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!found.empty()) 25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 25211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::check \n"); 25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert error += found; 25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline void 26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert check_constructed(void* p) 26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto found = map_construct().find(p); 26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (found == map_construct().end()) 26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::check_constructed not " 26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "constructed!\n"); 26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(error, std::make_pair(p, get_label())); 26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline void 27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert check_constructed(size_t label) 27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto beg = map_construct().begin(); 27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto end = map_construct().end(); 27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string found; 27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (beg != end) 27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (beg->second == label) 28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(found, *beg); 28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++beg; 28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!found.empty()) 28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error("annotate_base::check_constructed by label\n"); 28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert error += found; 28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_logic_error(error.c_str()); 29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert private: 29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::pair<size_t, size_t> data_type; 29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::map<void*, data_type> map_alloc_type; 29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef map_alloc_type::value_type entry_type; 29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef map_alloc_type::const_iterator const_iterator; 29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef map_alloc_type::const_reference const_reference; 30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::map<void*, size_t> map_construct_type; 30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert friend std::ostream& 30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator<<(std::ostream&, const annotate_base&); 30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert entry_type 30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert make_entry(void* p, size_t size) 30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { return std::make_pair(p, data_type(get_label(), size)); } 31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void 31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(std::string& s, const_reference ref) 31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char buf[40]; 31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char tab('\t'); 31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += "label: "; 31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned long l = static_cast<unsigned long>(ref.second.first); 31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __builtin_sprintf(buf, "%lu", l); 31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += buf; 32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += tab; 32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += "size: "; 32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert l = static_cast<unsigned long>(ref.second.second); 32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __builtin_sprintf(buf, "%lu", l); 32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += buf; 32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += tab; 32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += "address: "; 32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __builtin_sprintf(buf, "%p", ref.first); 32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += buf; 32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += '\n'; 33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void 33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert log_to_string(std::string& s, const std::pair<const void*, size_t>& ref) 33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char buf[40]; 33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char tab('\t'); 33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += "label: "; 33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unsigned long l = static_cast<unsigned long>(ref.second); 34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __builtin_sprintf(buf, "%lu", l); 34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += buf; 34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += tab; 34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += "address: "; 34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __builtin_sprintf(buf, "%p", ref.first); 34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += buf; 34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert s += '\n'; 34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static size_t& 35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert label() 35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static size_t _S_label(std::numeric_limits<size_t>::max()); 35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _S_label; 35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static map_alloc_type& 35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert map_alloc() 35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static map_alloc_type _S_map; 36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _S_map; 36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static map_construct_type& 36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert map_construct() 36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static map_construct_type _S_map; 36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _S_map; 37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline std::ostream& 37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator<<(std::ostream& os, const annotate_base& __b) 37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string error; 37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef annotate_base base_type; 37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert base_type::const_iterator beg = __b.map_alloc().begin(); 38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert base_type::const_iterator end = __b.map_alloc().end(); 38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (; beg != end; ++beg) 38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __b.log_to_string(error, *beg); 38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto beg = __b.map_construct().begin(); 38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert auto end = __b.map_construct().end(); 38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (; beg != end; ++beg) 39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __b.log_to_string(error, *beg); 39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return os << error; 39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /** 39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * @brief Base struct for condition policy. 39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Requires a public member function with the signature 40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * void throw_conditionally() 40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct condition_base 40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual ~condition_base() { }; 40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /** 41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * @brief Base class for incremental control and throw. 41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct limit_condition : public condition_base 41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Scope-level adjustor objects: set limit for throw at the 41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // beginning of a scope block, and restores to previous limit when 41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // object is destroyed on exiting the block. 41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct adjustor_base 41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert private: 42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const size_t _M_orig; 42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert public: 42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert adjustor_base() : _M_orig(limit()) { } 42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual 42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ~adjustor_base() { set_limit(_M_orig); } 42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Never enter the condition. 43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct never_adjustor : public adjustor_base 43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert never_adjustor() { set_limit(std::numeric_limits<size_t>::max()); } 43311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Always enter the condition. 43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct always_adjustor : public adjustor_base 43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert always_adjustor() { set_limit(count()); } 43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Enter the nth condition. 44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct limit_adjustor : public adjustor_base 44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert limit_adjustor(const size_t __l) { set_limit(__l); } 44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Increment _S_count every time called. 44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If _S_count matches the limit count, throw. 44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void 45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_conditionally() 45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (count() == limit()) 45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __throw_forced_error(); 45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++count(); 45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static size_t& 45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert count() 45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static size_t _S_count(0); 46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _S_count; 46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 46411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static size_t& 46511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert limit() 46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static size_t _S_limit(std::numeric_limits<size_t>::max()); 46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _S_limit; 46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Zero the throw counter, set limit to argument. 47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void 47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_limit(const size_t __l) 47411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 47511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert limit() = __l; 47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert count() = 0; 47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 48011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 48111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /** 48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * @brief Base class for random probability control and throw. 48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct random_condition : public condition_base 48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Scope-level adjustor objects: set probability for throw at the 48711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // beginning of a scope block, and restores to previous 48811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // probability when object is destroyed on exiting the block. 48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct adjustor_base 49011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert private: 49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const double _M_orig; 49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 49411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert public: 49511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert adjustor_base() : _M_orig(probability()) { } 49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual ~adjustor_base() 49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { set_probability(_M_orig); } 49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 50011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 50111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Group condition. 50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct group_adjustor : public adjustor_base 50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert group_adjustor(size_t size) 50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { set_probability(1 - std::pow(double(1 - probability()), 50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert double(0.5 / (size + 1)))); 50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Never enter the condition. 51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct never_adjustor : public adjustor_base 51211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 51311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert never_adjustor() { set_probability(0); } 51411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 51511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 51611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Always enter the condition. 51711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct always_adjustor : public adjustor_base 51811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 51911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert always_adjustor() { set_probability(1); } 52011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 52111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 52211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert random_condition() 52311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 52411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert probability(); 52511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert engine(); 52611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 52711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 52811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void 52911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert set_probability(double __p) 53011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { probability() = __p; } 53111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 53211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void 53311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_conditionally() 53411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 53511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (generate() < probability()) 53611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __throw_forced_error(); 53711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 53811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 53911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 54011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert seed(unsigned long __s) 54111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { engine().seed(__s); } 54211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 54311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert private: 54411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 54511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::uniform_real_distribution<double> distribution_type; 54611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::mt19937 engine_type; 54711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else 54811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::tr1::uniform_real<double> distribution_type; 54911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::tr1::mt19937 engine_type; 55011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 55111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 55211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static double 55311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert generate() 55411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 55511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 55611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const distribution_type distribution(0, 1); 55711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static auto generator = std::bind(distribution, engine()); 55811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else 55911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Use variate_generator to get normalized results. 56011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::tr1::variate_generator<engine_type, distribution_type> gen_t; 56111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert distribution_type distribution(0, 1); 56211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static gen_t generator(engine(), distribution); 56311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 56411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 56511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert double random = generator(); 56611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (random < distribution.min() || random > distribution.max()) 56711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 56811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::string __s("random_condition::generate"); 56911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __s += "\n"; 57011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __s += "random number generated is: "; 57111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert char buf[40]; 57211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __builtin_sprintf(buf, "%f", random); 57311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __s += buf; 57411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_out_of_range(__s.c_str()); 57511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 57611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 57711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return random; 57811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 57911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 58011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static double& 58111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert probability() 58211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 58311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static double _S_p; 58411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _S_p; 58511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 58611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 58711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static engine_type& 58811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert engine() 58911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 59011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static engine_type _S_e; 59111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _S_e; 59211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 59311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 59411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 59511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 59611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /** 59711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * @brief Class with exception generation control. Intended to be 59811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * used as a value_type in templatized code. 59911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 60011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Note: Destructor not allowed to throw. 60111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 60211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Cond> 60311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct throw_value_base : public _Cond 60411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 60511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef _Cond condition_type; 60611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 60711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert using condition_type::throw_conditionally; 60811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 60911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::size_t _M_i; 61011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 61111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifndef _GLIBCXX_IS_AGGREGATE 61211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_base() : _M_i(0) 61311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { throw_conditionally(); } 61411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 61511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_base(const throw_value_base& __v) : _M_i(__v._M_i) 61611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { throw_conditionally(); } 61711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 61811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 61911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Shall not throw. 62011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_base(throw_value_base&&) = default; 62111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 62211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 62311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert explicit throw_value_base(const std::size_t __i) : _M_i(__i) 62411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { throw_conditionally(); } 62511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 62611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 62711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_base& 62811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator=(const throw_value_base& __v) 62911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 63011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_conditionally(); 63111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _M_i = __v._M_i; 63211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return *this; 63311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 63411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 63511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 63611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Shall not throw. 63711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_base& 63811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator=(throw_value_base&&) = default; 63911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 64011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 64111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_base& 64211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator++() 64311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 64411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_conditionally(); 64511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++_M_i; 64611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return *this; 64711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 64811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 64911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 65011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Cond> 65111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline void 65211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert swap(throw_value_base<_Cond>& __a, throw_value_base<_Cond>& __b) 65311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 65411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef throw_value_base<_Cond> throw_value; 65511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value::throw_conditionally(); 65611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value orig(__a); 65711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __a = __b; 65811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __b = orig; 65911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 66011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 66111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // General instantiable types requirements. 66211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Cond> 66311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline bool 66411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator==(const throw_value_base<_Cond>& __a, 66511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const throw_value_base<_Cond>& __b) 66611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 66711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef throw_value_base<_Cond> throw_value; 66811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value::throw_conditionally(); 66911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool __ret = __a._M_i == __b._M_i; 67011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return __ret; 67111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 67211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 67311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Cond> 67411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline bool 67511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator<(const throw_value_base<_Cond>& __a, 67611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const throw_value_base<_Cond>& __b) 67711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 67811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef throw_value_base<_Cond> throw_value; 67911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value::throw_conditionally(); 68011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool __ret = __a._M_i < __b._M_i; 68111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return __ret; 68211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 68311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 68411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Numeric algorithms instantiable types requirements. 68511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Cond> 68611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline throw_value_base<_Cond> 68711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator+(const throw_value_base<_Cond>& __a, 68811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const throw_value_base<_Cond>& __b) 68911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 69011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef throw_value_base<_Cond> throw_value; 69111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value::throw_conditionally(); 69211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value __ret(__a._M_i + __b._M_i); 69311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return __ret; 69411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 69511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 69611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Cond> 69711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline throw_value_base<_Cond> 69811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator-(const throw_value_base<_Cond>& __a, 69911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const throw_value_base<_Cond>& __b) 70011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 70111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef throw_value_base<_Cond> throw_value; 70211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value::throw_conditionally(); 70311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value __ret(__a._M_i - __b._M_i); 70411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return __ret; 70511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 70611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 70711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Cond> 70811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline throw_value_base<_Cond> 70911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator*(const throw_value_base<_Cond>& __a, 71011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const throw_value_base<_Cond>& __b) 71111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 71211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef throw_value_base<_Cond> throw_value; 71311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value::throw_conditionally(); 71411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value __ret(__a._M_i * __b._M_i); 71511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return __ret; 71611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 71711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 71811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 71911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Type throwing via limit condition. 72011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct throw_value_limit : public throw_value_base<limit_condition> 72111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 72211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef throw_value_base<limit_condition> base_type; 72311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 72411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifndef _GLIBCXX_IS_AGGREGATE 72511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_limit() { } 72611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 72711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_limit(const throw_value_limit& __other) 72811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : base_type(__other._M_i) { } 72911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 73011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 73111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_limit(throw_value_limit&&) = default; 73211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 73311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 73411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert explicit throw_value_limit(const std::size_t __i) : base_type(__i) { } 73511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 73611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 73711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_limit& 73811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator=(const throw_value_limit& __other) 73911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 74011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert base_type::operator=(__other); 74111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return *this; 74211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 74311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 74411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 74511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_limit& 74611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator=(throw_value_limit&&) = default; 74711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 74811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 74911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 75011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Type throwing via random condition. 75111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct throw_value_random : public throw_value_base<random_condition> 75211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 75311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef throw_value_base<random_condition> base_type; 75411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 75511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifndef _GLIBCXX_IS_AGGREGATE 75611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_random() { } 75711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 75811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_random(const throw_value_random& __other) 75911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : base_type(__other._M_i) { } 76011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 76111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 76211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_random(throw_value_random&&) = default; 76311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 76411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 76511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert explicit throw_value_random(const std::size_t __i) : base_type(__i) { } 76611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 76711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 76811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_random& 76911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator=(const throw_value_random& __other) 77011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 77111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert base_type::operator=(__other); 77211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return *this; 77311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 77411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 77511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 77611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_value_random& 77711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator=(throw_value_random&&) = default; 77811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 77911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 78011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 78111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 78211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /** 78311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * @brief Allocator class with logging and exception generation control. 78411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Intended to be used as an allocator_type in templatized code. 78511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * @ingroup allocators 78611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * 78711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Note: Deallocate not allowed to throw. 78811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */ 78911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Tp, typename _Cond> 79011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert class throw_allocator_base 79111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : public annotate_base, public _Cond 79211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 79311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert public: 79411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef size_t size_type; 79511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef ptrdiff_t difference_type; 79611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef _Tp value_type; 79711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef value_type* pointer; 79811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef const value_type* const_pointer; 79911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef value_type& reference; 80011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef const value_type& const_reference; 80111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 80211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 80311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // _GLIBCXX_RESOLVE_LIB_DEFECTS 80411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // 2103. std::allocator propagate_on_container_move_assignment 80511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::true_type propagate_on_container_move_assignment; 80611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 80711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 80811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert private: 80911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef _Cond condition_type; 81011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 81111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::allocator<value_type> _M_allocator; 81211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 81311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert using condition_type::throw_conditionally; 81411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 81511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert public: 81611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_type 81711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert max_size() const _GLIBCXX_USE_NOEXCEPT 81811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { return _M_allocator.max_size(); } 81911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 82011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pointer 82111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert address(reference __x) const _GLIBCXX_NOEXCEPT 82211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { return std::__addressof(__x); } 82311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 82411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const_pointer 82511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert address(const_reference __x) const _GLIBCXX_NOEXCEPT 82611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { return std::__addressof(__x); } 82711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 82811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pointer 82911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert allocate(size_type __n, std::allocator<void>::const_pointer hint = 0) 83011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 83111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (__n > this->max_size()) 83211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::__throw_bad_alloc(); 83311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 83411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_conditionally(); 83511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pointer const a = _M_allocator.allocate(__n, hint); 83611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert insert(a, sizeof(value_type) * __n); 83711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return a; 83811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 83911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 84011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 84111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Up, typename... _Args> 84211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 84311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert construct(_Up* __p, _Args&&... __args) 84411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 84511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _M_allocator.construct(__p, std::forward<_Args>(__args)...); 84611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert insert_construct(__p); 84711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 84811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 84911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Up> 85011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 85111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert destroy(_Up* __p) 85211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 85311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert erase_construct(__p); 85411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _M_allocator.destroy(__p); 85511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 85611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else 85711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 85811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert construct(pointer __p, const value_type& val) 85911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { return _M_allocator.construct(__p, val); } 86011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 86111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 86211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert destroy(pointer __p) 86311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { _M_allocator.destroy(__p); } 86411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 86511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 86611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 86711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert deallocate(pointer __p, size_type __n) 86811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 86911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert erase(__p, sizeof(value_type) * __n); 87011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _M_allocator.deallocate(__p, __n); 87111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 87211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 87311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 87411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert check_allocated(pointer __p, size_type __n) 87511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 87611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_type __t = sizeof(value_type) * __n; 87711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert annotate_base::check_allocated(__p, __t); 87811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 87911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 88011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void 88111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert check(size_type __n) 88211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { annotate_base::check(__n); } 88311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 88411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 88511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Tp, typename _Cond> 88611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline bool 88711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator==(const throw_allocator_base<_Tp, _Cond>&, 88811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const throw_allocator_base<_Tp, _Cond>&) 88911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { return true; } 89011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 89111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Tp, typename _Cond> 89211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert inline bool 89311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator!=(const throw_allocator_base<_Tp, _Cond>&, 89411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const throw_allocator_base<_Tp, _Cond>&) 89511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { return false; } 89611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 89711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Allocator throwing via limit condition. 89811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Tp> 89911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct throw_allocator_limit 90011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : public throw_allocator_base<_Tp, limit_condition> 90111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 90211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Tp1> 90311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct rebind 90411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { typedef throw_allocator_limit<_Tp1> other; }; 90511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 90611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { } 90711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 90811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_allocator_limit(const throw_allocator_limit&) 90911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _GLIBCXX_USE_NOEXCEPT { } 91011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 91111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Tp1> 91211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_allocator_limit(const throw_allocator_limit<_Tp1>&) 91311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _GLIBCXX_USE_NOEXCEPT { } 91411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 91511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ~throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { } 91611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 91711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 91811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Allocator throwing via random condition. 91911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Tp> 92011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct throw_allocator_random 92111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : public throw_allocator_base<_Tp, random_condition> 92211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 92311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Tp1> 92411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct rebind 92511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { typedef throw_allocator_random<_Tp1> other; }; 92611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 92711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { } 92811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 92911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_allocator_random(const throw_allocator_random&) 93011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _GLIBCXX_USE_NOEXCEPT { } 93111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 93211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<typename _Tp1> 93311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert throw_allocator_random(const throw_allocator_random<_Tp1>&) 93411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _GLIBCXX_USE_NOEXCEPT { } 93511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 93611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ~throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { } 93711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 93811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 93911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert_GLIBCXX_END_NAMESPACE_VERSION 94011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} // namespace 94111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 94211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if __cplusplus >= 201103L 94311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 94411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert# include <bits/functional_hash.h> 94511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 94611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertnamespace std _GLIBCXX_VISIBILITY(default) 94711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{ 94811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Explicit specialization of std::hash for __gnu_cxx::throw_value_limit. 94911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<> 95011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct hash<__gnu_cxx::throw_value_limit> 95111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : public std::unary_function<__gnu_cxx::throw_value_limit, size_t> 95211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 95311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t 95411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator()(const __gnu_cxx::throw_value_limit& __val) const 95511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 95611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __gnu_cxx::throw_value_limit::throw_conditionally(); 95711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::hash<std::size_t> __h; 95811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t __result = __h(__val._M_i); 95911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return __result; 96011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 96111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 96211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 96311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert /// Explicit specialization of std::hash for __gnu_cxx::throw_value_random. 96411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert template<> 96511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct hash<__gnu_cxx::throw_value_random> 96611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : public std::unary_function<__gnu_cxx::throw_value_random, size_t> 96711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 96811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t 96911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert operator()(const __gnu_cxx::throw_value_random& __val) const 97011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert { 97111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert __gnu_cxx::throw_value_random::throw_conditionally(); 97211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert std::hash<std::size_t> __h; 97311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t __result = __h(__val._M_i); 97411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return __result; 97511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 97611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 97711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} // end namespace std 97811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 97911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 98011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 981