Commit 12cde21b by Benjamin Kosnik Committed by Benjamin Kosnik

re PR libstdc++/17780 (std::allocator vs. static init)


2004-10-05  Benjamin Kosnik  <bkoz@redhat.com>

	PR libstdc++/17780
	* include/ext/mt_allocator.h (__pool_base::_Tune): Add default
	options as compile-time constant enums.
	(__pool_base::_Tune::is_default): New.
	(__pool_base::_Block_address): New.
	(__pool_base): Rearrange data members.
	(__pool::_M_reserve_memory): To _M_reserve_block.
	(__pool::_M_reclaim_memory): To _M_reclaim_block.
	(__pool::_Bin_record): Add _Block_address data member.
	(__pool<false>): Add _M_thread_freelist_initial.
	(__pool::~__pool): Declare.
	(__common_pool_policy): Move static data member to...
	(__common_pool_policy::_S_get_pool): ...here, make static local.
	(__per_type_pool_policy): Move static data member to...
	(__per_type_pool_policy::_S_get_pool): ...here, make static local.
	(__mt_alloc::__mt_alloc): Call __policy_type::_S_get_pool.
	Remove static member definitions. Use define for __default_policy.
	* src/mt_allocator.cc: Same.
	* config/linker-map.gnu: Don't export _S_get_pool. Renames.
	* testsuite/ext/new_allocator: New.
	* testsuite/ext/new_allocator/instantiate.cc: New.
	* testsuite/ext/new_allocator/check_new.cc: New.
	* testsuite/ext/new_allocator/deallocate_global.cc: New.
	* testsuite/ext/new_allocator/deallocate_local.cc: New.
	* testsuite/ext/mt_allocator/instantiate.cc: Instantiate all
	template arguments.
	* testsuite/ext/mt_allocator/deallocate_global-1.cc: New.
	* testsuite/ext/mt_allocator/deallocate_global-2.cc: New.
	* testsuite/ext/mt_allocator/deallocate_global-3.cc: New.
	* testsuite/ext/mt_allocator/deallocate_global-4.cc: New.
	* testsuite/ext/mt_allocator/deallocate_local-1.cc: New.
	* testsuite/ext/mt_allocator/deallocate_local-2.cc: New.
	* testsuite/ext/mt_allocator/deallocate_local-3.cc: New.
	* testsuite/ext/mt_allocator/deallocate_local-4.cc: New.
	* testsuite/ext/mt_allocator/deallocate.cc: New.
	* testsuite/ext/malloc_allocator/deallocate.cc: New.
	* testsuite/ext/malloc_allocator/deallocate_global.cc: New.
	* testsuite/ext/malloc_allocator/deallocate_local.cc: New.

From-SVN: r88589
parent 743eeb5a
2004-10-05 Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/17780
* include/ext/mt_allocator.h (__pool_base::_Tune): Add default
options as compile-time constant enums.
(__pool_base::_Tune::is_default): New.
(__pool_base::_Block_address): New.
(__pool_base): Rearrange data members.
(__pool::_M_reserve_memory): To _M_reserve_block.
(__pool::_M_reclaim_memory): To _M_reclaim_block.
(__pool::_Bin_record): Add _Block_address data member.
(__pool<false>): Add _M_thread_freelist_initial.
(__pool::~__pool): Declare.
(__common_pool_policy): Move static data member to...
(__common_pool_policy::_S_get_pool): ...here, make static local.
(__per_type_pool_policy): Move static data member to...
(__per_type_pool_policy::_S_get_pool): ...here, make static local.
(__mt_alloc::__mt_alloc): Call __policy_type::_S_get_pool.
Remove static member definitions. Use define for __default_policy.
* src/mt_allocator.cc: Same.
* config/linker-map.gnu: Don't export _S_get_pool. Renames.
* testsuite/ext/new_allocator: New.
* testsuite/ext/new_allocator/instantiate.cc: New.
* testsuite/ext/new_allocator/check_new.cc: New.
* testsuite/ext/new_allocator/deallocate_global.cc: New.
* testsuite/ext/new_allocator/deallocate_local.cc: New.
* testsuite/ext/mt_allocator/instantiate.cc: Instantiate all
template arguments.
* testsuite/ext/mt_allocator/deallocate_global-1.cc: New.
* testsuite/ext/mt_allocator/deallocate_global-2.cc: New.
* testsuite/ext/mt_allocator/deallocate_global-3.cc: New.
* testsuite/ext/mt_allocator/deallocate_global-4.cc: New.
* testsuite/ext/mt_allocator/deallocate_local-1.cc: New.
* testsuite/ext/mt_allocator/deallocate_local-2.cc: New.
* testsuite/ext/mt_allocator/deallocate_local-3.cc: New.
* testsuite/ext/mt_allocator/deallocate_local-4.cc: New.
* testsuite/ext/mt_allocator/deallocate.cc: New.
* testsuite/ext/malloc_allocator/deallocate.cc: New.
* testsuite/ext/malloc_allocator/deallocate_global.cc: New.
* testsuite/ext/malloc_allocator/deallocate_local.cc: New.
2004-10-05 Ulrich Weigand <uweigand@de.ibm.com> 2004-10-05 Ulrich Weigand <uweigand@de.ibm.com>
* configure.host (abi_baseline_pair): Define for s390-*-linux* and * configure.host (abi_baseline_pair): Define for s390-*-linux* and
......
...@@ -267,9 +267,9 @@ GLIBCXX_3.4.3 { ...@@ -267,9 +267,9 @@ GLIBCXX_3.4.3 {
_ZN9__gnu_cxx6__poolILb1EE13_M_initializeEPFvPvE; _ZN9__gnu_cxx6__poolILb1EE13_M_initializeEPFvPvE;
_ZN9__gnu_cxx6__poolILb1EE21_M_destroy_thread_keyEPv; _ZN9__gnu_cxx6__poolILb1EE21_M_destroy_thread_keyEPv;
_ZN9__gnu_cxx6__poolILb1EE16_M_get_thread_idEv; _ZN9__gnu_cxx6__poolILb1EE16_M_get_thread_idEv;
_ZN9__gnu_cxx6__poolILb[01]EE17_M_reserve_memoryE[jm][jm]; _ZN9__gnu_cxx6__poolILb[01]EE16_M_reserve_blockE[jm][jm];
_ZN9__gnu_cxx6__poolILb[01]EE17_M_reclaim_memoryEPc[jm]; _ZN9__gnu_cxx6__poolILb[01]EE16_M_reclaim_blockEPc[jm];
_ZN9__gnu_cxx20__common_pool_policyILb[01]EE11_S_get_poolEv; _ZN9__gnu_cxx6__poolILb[01]EED[12]Ev;
# stub functions from libmath # stub functions from libmath
acosf; acosf;
......
...@@ -56,17 +56,28 @@ namespace __gnu_cxx ...@@ -56,17 +56,28 @@ namespace __gnu_cxx
typedef void (*__destroy_handler)(void*); typedef void (*__destroy_handler)(void*);
typedef void (*__create_handler)(void); typedef void (*__create_handler)(void);
class __pool_base struct __pool_base
{ {
public: // Using short int as type for the binmap implies we are never
// caching blocks larger than 65535 with this allocator.
typedef unsigned short int _Binmap_type;
// Variables used to configure the behavior of the allocator, // Variables used to configure the behavior of the allocator,
// assigned and explained in detail below. // assigned and explained in detail below.
struct _Tune struct _Tune
{ {
// Compile time constants for the default _Tune values.
enum { _S_align = 8 };
enum { _S_max_bytes = 128 };
enum { _S_min_bin = 8 };
enum { _S_chunk_size = 4096 - 4 * sizeof(void*) };
enum { _S_max_threads = 4096 };
enum { _S_freelist_headroom = 10 };
// Alignment needed. // Alignment needed.
// NB: In any case must be >= sizeof(_Block_record), that // NB: In any case must be >= sizeof(_Block_record), that
// is 4 on 32 bit machines and 8 on 64 bit machines. // is 4 on 32 bit machines and 8 on 64 bit machines.
size_t _M_align; size_t _M_align;
// Allocation requests (after round-up to power of 2) below // Allocation requests (after round-up to power of 2) below
// this value will be handled by the allocator. A raw new/ // this value will be handled by the allocator. A raw new/
...@@ -75,14 +86,14 @@ namespace __gnu_cxx ...@@ -75,14 +86,14 @@ namespace __gnu_cxx
// Size in bytes of the smallest bin. // Size in bytes of the smallest bin.
// NB: Must be a power of 2 and >= _M_align. // NB: Must be a power of 2 and >= _M_align.
size_t _M_min_bin; size_t _M_min_bin;
// In order to avoid fragmenting and minimize the number of // In order to avoid fragmenting and minimize the number of
// new() calls we always request new memory using this // new() calls we always request new memory using this
// value. Based on previous discussions on the libstdc++ // value. Based on previous discussions on the libstdc++
// mailing list we have choosen the value below. // mailing list we have choosen the value below.
// See http://gcc.gnu.org/ml/libstdc++/2001-07/msg00077.html // See http://gcc.gnu.org/ml/libstdc++/2001-07/msg00077.html
size_t _M_chunk_size; size_t _M_chunk_size;
// The maximum number of supported threads. For // The maximum number of supported threads. For
// single-threaded operation, use one. Maximum values will // single-threaded operation, use one. Maximum values will
...@@ -105,9 +116,9 @@ namespace __gnu_cxx ...@@ -105,9 +116,9 @@ namespace __gnu_cxx
explicit explicit
_Tune() _Tune()
: _M_align(8), _M_max_bytes(128), _M_min_bin(8), : _M_align(_S_align), _M_max_bytes(_S_max_bytes), _M_min_bin(_S_min_bin),
_M_chunk_size(4096 - 4 * sizeof(void*)), _M_chunk_size(_S_chunk_size), _M_max_threads(_S_max_threads),
_M_max_threads(4096), _M_freelist_headroom(10), _M_freelist_headroom(_S_freelist_headroom),
_M_force_new(getenv("GLIBCXX_FORCE_NEW") ? true : false) _M_force_new(getenv("GLIBCXX_FORCE_NEW") ? true : false)
{ } { }
...@@ -118,6 +129,25 @@ namespace __gnu_cxx ...@@ -118,6 +129,25 @@ namespace __gnu_cxx
_M_chunk_size(__chunk), _M_max_threads(__maxthreads), _M_chunk_size(__chunk), _M_max_threads(__maxthreads),
_M_freelist_headroom(__headroom), _M_force_new(__force) _M_freelist_headroom(__headroom), _M_force_new(__force)
{ } { }
bool
is_default() const
{
bool __ret = true;
__ret &= _M_align == _S_align;
__ret &= _M_max_bytes == _S_max_bytes;
__ret &= _M_min_bin == _S_min_bin;
__ret &= _M_chunk_size == _S_chunk_size;
__ret &= _M_max_threads == _S_max_threads;
__ret &= _M_freelist_headroom == _S_freelist_headroom;
return __ret;
}
};
struct _Block_address
{
void* _M_initial;
_Block_address* _M_next;
}; };
const _Tune& const _Tune&
...@@ -140,20 +170,17 @@ namespace __gnu_cxx ...@@ -140,20 +170,17 @@ namespace __gnu_cxx
{ return _M_binmap[__bytes]; } { return _M_binmap[__bytes]; }
explicit __pool_base() explicit __pool_base()
: _M_init(false), _M_options(_Tune()), _M_binmap(NULL) { } : _M_options(_Tune()), _M_binmap(NULL), _M_init(false) { }
protected: protected:
// We need to create the initial lists and set up some variables
// before we can answer to the first request for memory.
bool _M_init;
// Configuration options. // Configuration options.
_Tune _M_options; _Tune _M_options;
// Using short int as type for the binmap implies we are never
// caching blocks larger than 65535 with this allocator.
typedef unsigned short int _Binmap_type;
_Binmap_type* _M_binmap; _Binmap_type* _M_binmap;
// We need to create the initial lists and set up some variables
// before we can answer to the first request for memory.
bool _M_init;
}; };
// Data describing the underlying memory pool, parameterized on // Data describing the underlying memory pool, parameterized on
...@@ -204,10 +231,13 @@ namespace __gnu_cxx ...@@ -204,10 +231,13 @@ namespace __gnu_cxx
struct _Bin_record struct _Bin_record
{ {
// An "array" of pointers to the first free block for each // An "array" of pointers to the first free block for each
// thread id. Memory to this "array" is allocated in _S_initialize() // thread id. Memory to this "array" is allocated in
// for _S_max_threads + global pool 0. // _S_initialize() for _S_max_threads + global pool 0.
_Block_record** volatile _M_first; _Block_record** volatile _M_first;
// A list of the initial addresses of all allocated blocks.
_Block_address* _M_address;
// An "array" of counters used to keep track of the amount of // An "array" of counters used to keep track of the amount of
// blocks that are on the freelist/used for each thread id. // blocks that are on the freelist/used for each thread id.
// Memory to these "arrays" is allocated in _S_initialize() for // Memory to these "arrays" is allocated in _S_initialize() for
...@@ -242,10 +272,10 @@ namespace __gnu_cxx ...@@ -242,10 +272,10 @@ namespace __gnu_cxx
} }
char* char*
_M_reserve_memory(size_t __bytes, const size_t __thread_id); _M_reserve_block(size_t __bytes, const size_t __thread_id);
void void
_M_reclaim_memory(char* __p, size_t __bytes); _M_reclaim_block(char* __p, size_t __bytes);
const _Bin_record& const _Bin_record&
_M_get_bin(size_t __which) _M_get_bin(size_t __which)
...@@ -277,6 +307,8 @@ namespace __gnu_cxx ...@@ -277,6 +307,8 @@ namespace __gnu_cxx
_M_once = __tmp; _M_once = __tmp;
} }
~__pool();
private: private:
// An "array" of bin_records each of which represents a specific // An "array" of bin_records each of which represents a specific
// power of 2 size. Memory to this "array" is allocated in // power of 2 size. Memory to this "array" is allocated in
...@@ -289,6 +321,7 @@ namespace __gnu_cxx ...@@ -289,6 +321,7 @@ namespace __gnu_cxx
__gthread_once_t _M_once; __gthread_once_t _M_once;
_Thread_record* _M_thread_freelist; _Thread_record* _M_thread_freelist;
void* _M_thread_freelist_initial;
}; };
#endif #endif
...@@ -302,13 +335,14 @@ namespace __gnu_cxx ...@@ -302,13 +335,14 @@ namespace __gnu_cxx
// Points to the block_record of the next free block. // Points to the block_record of the next free block.
_Block_record* volatile _M_next; _Block_record* volatile _M_next;
}; };
struct _Bin_record struct _Bin_record
{ {
// An "array" of pointers to the first free block for each // An "array" of pointers to the first free block.
// thread id. Memory to this "array" is allocated in _S_initialize()
// for _S_max_threads + global pool 0.
_Block_record** volatile _M_first; _Block_record** volatile _M_first;
// A list of the initial addresses of all allocated blocks.
_Block_address* _M_address;
}; };
void void
...@@ -319,10 +353,10 @@ namespace __gnu_cxx ...@@ -319,10 +353,10 @@ namespace __gnu_cxx
} }
char* char*
_M_reserve_memory(size_t __bytes, const size_t __thread_id); _M_reserve_block(size_t __bytes, const size_t __thread_id);
void void
_M_reclaim_memory(char* __p, size_t __bytes); _M_reclaim_block(char* __p, size_t __bytes);
size_t size_t
_M_get_thread_id() { return 0; } _M_get_thread_id() { return 0; }
...@@ -337,7 +371,9 @@ namespace __gnu_cxx ...@@ -337,7 +371,9 @@ namespace __gnu_cxx
explicit __pool() explicit __pool()
: _M_bin(NULL), _M_bin_size(1) { } : _M_bin(NULL), _M_bin_size(1) { }
~__pool();
private: private:
// An "array" of bin_records each of which represents a specific // An "array" of bin_records each of which represents a specific
// power of 2 size. Memory to this "array" is allocated in // power of 2 size. Memory to this "array" is allocated in
...@@ -351,10 +387,11 @@ namespace __gnu_cxx ...@@ -351,10 +387,11 @@ namespace __gnu_cxx
_M_initialize(); _M_initialize();
}; };
template<bool _Thread> template<bool _Thread>
struct __common_pool_policy struct __common_pool_policy
{ {
typedef __pool<_Thread> __pool_type;
template<typename _Tp1, bool _Thread1 = _Thread> template<typename _Tp1, bool _Thread1 = _Thread>
struct _M_rebind; struct _M_rebind;
...@@ -366,11 +403,12 @@ namespace __gnu_cxx ...@@ -366,11 +403,12 @@ namespace __gnu_cxx
struct _M_rebind<_Tp1, false> struct _M_rebind<_Tp1, false>
{ typedef __common_pool_policy<false> other; }; { typedef __common_pool_policy<false> other; };
typedef __pool<_Thread> __pool_type;
static __pool_type _S_data;
static __pool_type& static __pool_type&
_S_get_pool(); _S_get_pool()
{
static __pool_type _S_pool;
return _S_pool;
}
static void static void
_S_initialize_once() _S_initialize_once()
...@@ -391,6 +429,8 @@ namespace __gnu_cxx ...@@ -391,6 +429,8 @@ namespace __gnu_cxx
template<> template<>
struct __common_pool_policy<true> struct __common_pool_policy<true>
{ {
typedef __pool<true> __pool_type;
template<typename _Tp1, bool _Thread1 = true> template<typename _Tp1, bool _Thread1 = true>
struct _M_rebind; struct _M_rebind;
...@@ -402,11 +442,12 @@ namespace __gnu_cxx ...@@ -402,11 +442,12 @@ namespace __gnu_cxx
struct _M_rebind<_Tp1, false> struct _M_rebind<_Tp1, false>
{ typedef __common_pool_policy<false> other; }; { typedef __common_pool_policy<false> other; };
typedef __pool<true> __pool_type;
static __pool_type _S_data;
static __pool_type& static __pool_type&
_S_get_pool(); _S_get_pool()
{
static __pool_type _S_pool;
return _S_pool;
}
static void static void
_S_destroy_thread_key(void* __freelist_pos) _S_destroy_thread_key(void* __freelist_pos)
...@@ -429,9 +470,12 @@ namespace __gnu_cxx ...@@ -429,9 +470,12 @@ namespace __gnu_cxx
}; };
#endif #endif
template<typename _Tp, bool _Thread> template<typename _Tp, bool _Thread>
struct __per_type_pool_policy struct __per_type_pool_policy
{ {
typedef __pool<_Thread> __pool_type;
template<typename _Tp1, bool _Thread1 = _Thread> template<typename _Tp1, bool _Thread1 = _Thread>
struct _M_rebind; struct _M_rebind;
...@@ -443,11 +487,13 @@ namespace __gnu_cxx ...@@ -443,11 +487,13 @@ namespace __gnu_cxx
struct _M_rebind<_Tp1, true> struct _M_rebind<_Tp1, true>
{ typedef __per_type_pool_policy<_Tp1, true> other; }; { typedef __per_type_pool_policy<_Tp1, true> other; };
typedef __pool<_Thread> __pool_type; // Avoid static initialization ordering issues.
static __pool_type _S_data;
static __pool_type& static __pool_type&
_S_get_pool( ) { return _S_data; } _S_get_pool()
{
static __pool_type _S_pool;
return _S_pool;
}
static void static void
_S_initialize_once() _S_initialize_once()
...@@ -461,10 +507,6 @@ namespace __gnu_cxx ...@@ -461,10 +507,6 @@ namespace __gnu_cxx
} }
}; };
template<typename _Tp, bool _Thread>
__pool<_Thread>
__per_type_pool_policy<_Tp, _Thread>::_S_data;
template<typename _Tp> template<typename _Tp>
struct __per_type_pool_policy<_Tp, true>; struct __per_type_pool_policy<_Tp, true>;
...@@ -472,6 +514,8 @@ namespace __gnu_cxx ...@@ -472,6 +514,8 @@ namespace __gnu_cxx
template<typename _Tp> template<typename _Tp>
struct __per_type_pool_policy<_Tp, true> struct __per_type_pool_policy<_Tp, true>
{ {
typedef __pool<true> __pool_type;
template<typename _Tp1, bool _Thread1 = true> template<typename _Tp1, bool _Thread1 = true>
struct _M_rebind; struct _M_rebind;
...@@ -483,11 +527,13 @@ namespace __gnu_cxx ...@@ -483,11 +527,13 @@ namespace __gnu_cxx
struct _M_rebind<_Tp1, true> struct _M_rebind<_Tp1, true>
{ typedef __per_type_pool_policy<_Tp1, true> other; }; { typedef __per_type_pool_policy<_Tp1, true> other; };
typedef __pool<true> __pool_type; // Avoid static initialization ordering issues.
static __pool_type _S_data;
static __pool_type& static __pool_type&
_S_get_pool( ) { return _S_data; } _S_get_pool( )
{
static __pool_type _S_pool;
return _S_pool;
}
static void static void
_S_destroy_thread_key(void* __freelist_pos) _S_destroy_thread_key(void* __freelist_pos)
...@@ -508,16 +554,6 @@ namespace __gnu_cxx ...@@ -508,16 +554,6 @@ namespace __gnu_cxx
} }
} }
}; };
template<typename _Tp>
__pool<true>
__per_type_pool_policy<_Tp, true>::_S_data;
#endif
#ifdef __GTHREADS
typedef __common_pool_policy<true> __default_policy;
#else
typedef __common_pool_policy<false> __default_policy;
#endif #endif
template<typename _Tp> template<typename _Tp>
...@@ -554,8 +590,14 @@ namespace __gnu_cxx ...@@ -554,8 +590,14 @@ namespace __gnu_cxx
destroy(pointer __p) { __p->~_Tp(); } destroy(pointer __p) { __p->~_Tp(); }
}; };
#ifdef __GTHREADS
#define __default_policy __common_pool_policy<true>
#else
#define __default_policy __common_pool_policy<false>
#endif
template<typename _Tp, typename _Poolp = __default_policy> template<typename _Tp, typename _Poolp = __default_policy>
class __mt_alloc : public __mt_alloc_base<_Tp>, _Poolp class __mt_alloc : public __mt_alloc_base<_Tp>, _Poolp
{ {
public: public:
typedef size_t size_type; typedef size_t size_type;
...@@ -575,21 +617,18 @@ namespace __gnu_cxx ...@@ -575,21 +617,18 @@ namespace __gnu_cxx
typedef __mt_alloc<_Tp1, pol_type> other; typedef __mt_alloc<_Tp1, pol_type> other;
}; };
// Create pool instance so that order of construction will be
// pool_type first, then allocator. This is necessary for
// correct global and static object construction/destruction.
__mt_alloc() throw() __mt_alloc() throw()
{ { __policy_type::_S_get_pool(); }
// XXX
}
__mt_alloc(const __mt_alloc&) throw() __mt_alloc(const __mt_alloc&) throw()
{ { __policy_type::_S_get_pool(); }
// XXX
}
template<typename _Tp1, typename _Poolp1> template<typename _Tp1, typename _Poolp1>
__mt_alloc(const __mt_alloc<_Tp1, _Poolp1>& obj) throw() __mt_alloc(const __mt_alloc<_Tp1, _Poolp1>& obj) throw()
{ { __policy_type::_S_get_pool(); }
// XXX
}
~__mt_alloc() throw() { } ~__mt_alloc() throw() { }
...@@ -620,23 +659,23 @@ namespace __gnu_cxx ...@@ -620,23 +659,23 @@ namespace __gnu_cxx
// Requests larger than _M_max_bytes are handled by new/delete // Requests larger than _M_max_bytes are handled by new/delete
// directly. // directly.
__pool_type& __pl = this->_S_get_pool(); __pool_type& __pool = this->_S_get_pool();
const size_t __bytes = __n * sizeof(_Tp); const size_t __bytes = __n * sizeof(_Tp);
if (__pl._M_check_threshold(__bytes)) if (__pool._M_check_threshold(__bytes))
{ {
void* __ret = ::operator new(__bytes); void* __ret = ::operator new(__bytes);
return static_cast<_Tp*>(__ret); return static_cast<_Tp*>(__ret);
} }
// Round up to power of 2 and figure out which bin to use. // Round up to power of 2 and figure out which bin to use.
const size_t __which = __pl._M_get_binmap(__bytes); const size_t __which = __pool._M_get_binmap(__bytes);
const size_t __thread_id = __pl._M_get_thread_id(); const size_t __thread_id = __pool._M_get_thread_id();
// Find out if we have blocks on our freelist. If so, go ahead // Find out if we have blocks on our freelist. If so, go ahead
// and use them directly without having to lock anything. // and use them directly without having to lock anything.
char* __c; char* __c;
typedef typename __pool_type::_Bin_record _Bin_record; typedef typename __pool_type::_Bin_record _Bin_record;
const _Bin_record& __bin = __pl._M_get_bin(__which); const _Bin_record& __bin = __pool._M_get_bin(__which);
if (__bin._M_first[__thread_id]) if (__bin._M_first[__thread_id])
{ {
// Already reserved. // Already reserved.
...@@ -644,14 +683,14 @@ namespace __gnu_cxx ...@@ -644,14 +683,14 @@ namespace __gnu_cxx
_Block_record* __block = __bin._M_first[__thread_id]; _Block_record* __block = __bin._M_first[__thread_id];
__bin._M_first[__thread_id] = __bin._M_first[__thread_id]->_M_next; __bin._M_first[__thread_id] = __bin._M_first[__thread_id]->_M_next;
__pl._M_adjust_freelist(__bin, __block, __thread_id); __pool._M_adjust_freelist(__bin, __block, __thread_id);
const __pool_base::_Tune& __options = __pl._M_get_options(); const __pool_base::_Tune& __options = __pool._M_get_options();
__c = reinterpret_cast<char*>(__block) + __options._M_align; __c = reinterpret_cast<char*>(__block) + __options._M_align;
} }
else else
{ {
// Null, reserve. // Null, reserve.
__c = __pl._M_reserve_memory(__bytes, __thread_id); __c = __pool._M_reserve_block(__bytes, __thread_id);
} }
return static_cast<_Tp*>(static_cast<void*>(__c)); return static_cast<_Tp*>(static_cast<void*>(__c));
} }
...@@ -663,12 +702,12 @@ namespace __gnu_cxx ...@@ -663,12 +702,12 @@ namespace __gnu_cxx
{ {
// Requests larger than _M_max_bytes are handled by operators // Requests larger than _M_max_bytes are handled by operators
// new/delete directly. // new/delete directly.
__pool_type& __pl = this->_S_get_pool(); __pool_type& __pool = this->_S_get_pool();
const size_t __bytes = __n * sizeof(_Tp); const size_t __bytes = __n * sizeof(_Tp);
if (__pl._M_check_threshold(__bytes)) if (__pool._M_check_threshold(__bytes))
::operator delete(__p); ::operator delete(__p);
else else
__pl._M_reclaim_memory(reinterpret_cast<char*>(__p), __bytes); __pool._M_reclaim_block(reinterpret_cast<char*>(__p), __bytes);
} }
template<typename _Tp, typename _Poolp> template<typename _Tp, typename _Poolp>
...@@ -680,6 +719,8 @@ namespace __gnu_cxx ...@@ -680,6 +719,8 @@ namespace __gnu_cxx
inline bool inline bool
operator!=(const __mt_alloc<_Tp, _Poolp>&, const __mt_alloc<_Tp, _Poolp>&) operator!=(const __mt_alloc<_Tp, _Poolp>&, const __mt_alloc<_Tp, _Poolp>&)
{ return false; } { return false; }
#undef __default_policy
} // namespace __gnu_cxx } // namespace __gnu_cxx
#endif #endif
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
// //
#include <bits/c++config.h> #include <bits/c++config.h>
#include <ext/mt_allocator.h>
#include <bits/concurrence.h> #include <bits/concurrence.h>
#include <ext/mt_allocator.h>
namespace __gnu_internal namespace __gnu_internal
{ {
...@@ -46,18 +46,185 @@ namespace __gnu_internal ...@@ -46,18 +46,185 @@ namespace __gnu_internal
namespace __gnu_cxx namespace __gnu_cxx
{ {
__pool<false>::~__pool()
{
if (_M_init && !_M_options._M_force_new)
{
for (size_t __n = 0; __n < _M_bin_size; ++__n)
{
_Bin_record& __bin = _M_bin[__n];
while (__bin._M_address)
{
_Block_address* __tmp = __bin._M_address->_M_next;
::operator delete(__bin._M_address->_M_initial);
delete __bin._M_address;
__bin._M_address = __tmp;
}
delete __bin._M_first;
}
delete _M_bin;
delete _M_binmap;
}
}
void
__pool<false>::_M_reclaim_block(char* __p, size_t __bytes)
{
// Round up to power of 2 and figure out which bin to use.
const size_t __which = _M_binmap[__bytes];
_Bin_record& __bin = _M_bin[__which];
const _Tune& __options = _M_get_options();
char* __c = __p - __options._M_align;
_Block_record* __block = reinterpret_cast<_Block_record*>(__c);
// Single threaded application - return to global pool.
__block->_M_next = __bin._M_first[0];
__bin._M_first[0] = __block;
}
char*
__pool<false>::_M_reserve_block(size_t __bytes, const size_t __thread_id)
{
// Round up to power of 2 and figure out which bin to use.
const size_t __which = _M_binmap[__bytes];
const _Tune& __options = _M_get_options();
const size_t __bin_size = ((__options._M_min_bin << __which)
+ __options._M_align);
size_t __block_count = __options._M_chunk_size / __bin_size;
// Get a new block dynamically, set it up for use.
void* __v = ::operator new(__options._M_chunk_size);
_Block_record* __block = static_cast<_Block_record*>(__v);
--__block_count;
_Block_record* __tmp = __block;
while (__block_count-- > 0)
{
char* __c = reinterpret_cast<char*>(__tmp) + __bin_size;
__tmp->_M_next = reinterpret_cast<_Block_record*>(__c);
__tmp = __tmp->_M_next;
}
__tmp->_M_next = NULL;
// Update _Bin_record fields.
_Bin_record& __bin = _M_bin[__which];
__bin._M_first[__thread_id] = __block->_M_next;
_Block_address* __address = new _Block_address;
__address->_M_initial = __v;
__address->_M_next = __bin._M_address;
__bin._M_address = __address;
// NB: For alignment reasons, we can't use the first _M_align
// bytes, even when sizeof(_Block_record) < _M_align.
return reinterpret_cast<char*>(__block) + __options._M_align;
}
void
__pool<false>::_M_initialize()
{
// _M_force_new must not change after the first allocate(), which
// in turn calls this method, so if it's false, it's false forever
// and we don't need to return here ever again.
if (_M_options._M_force_new)
{
_M_init = true;
return;
}
// Create the bins.
// Calculate the number of bins required based on _M_max_bytes.
// _M_bin_size is statically-initialized to one.
size_t __bin_size = _M_options._M_min_bin;
while (_M_options._M_max_bytes > __bin_size)
{
__bin_size <<= 1;
++_M_bin_size;
}
// Setup the bin map for quick lookup of the relevant bin.
const size_t __j = (_M_options._M_max_bytes + 1) * sizeof(_Binmap_type);
_M_binmap = static_cast<_Binmap_type*>(::operator new(__j));
_Binmap_type* __bp = _M_binmap;
_Binmap_type __bin_max = _M_options._M_min_bin;
_Binmap_type __bint = 0;
for (_Binmap_type __ct = 0; __ct <= _M_options._M_max_bytes; ++__ct)
{
if (__ct > __bin_max)
{
__bin_max <<= 1;
++__bint;
}
*__bp++ = __bint;
}
// Initialize _M_bin and its members.
void* __v = ::operator new(sizeof(_Bin_record) * _M_bin_size);
_M_bin = static_cast<_Bin_record*>(__v);
for (size_t __n = 0; __n < _M_bin_size; ++__n)
{
_Bin_record& __bin = _M_bin[__n];
__v = ::operator new(sizeof(_Block_record*));
__bin._M_first = static_cast<_Block_record**>(__v);
__bin._M_first[0] = NULL;
__bin._M_address = NULL;
}
_M_init = true;
}
#ifdef __GTHREADS #ifdef __GTHREADS
__pool<true>::~__pool()
{
if (_M_init && !_M_options._M_force_new)
{
if (__gthread_active_p())
{
for (size_t __n = 0; __n < _M_bin_size; ++__n)
{
_Bin_record& __bin = _M_bin[__n];
while (__bin._M_address)
{
_Block_address* __tmp = __bin._M_address->_M_next;
::operator delete(__bin._M_address->_M_initial);
delete __bin._M_address;
__bin._M_address = __tmp;
}
delete __bin._M_first;
delete __bin._M_free;
delete __bin._M_used;
delete __bin._M_mutex;
}
::operator delete(_M_thread_freelist_initial);
}
else
{
for (size_t __n = 0; __n < _M_bin_size; ++__n)
{
_Bin_record& __bin = _M_bin[__n];
while (__bin._M_address)
{
_Block_address* __tmp = __bin._M_address->_M_next;
::operator delete(__bin._M_address->_M_initial);
delete __bin._M_address;
__bin._M_address = __tmp;
}
delete __bin._M_first;
}
}
delete _M_bin;
delete _M_binmap;
}
}
void void
__pool<true>::_M_reclaim_memory(char* __p, size_t __bytes) __pool<true>::_M_reclaim_block(char* __p, size_t __bytes)
{ {
// Round up to power of 2 and figure out which bin to use. // Round up to power of 2 and figure out which bin to use.
const size_t __which = _M_binmap[__bytes]; const size_t __which = _M_binmap[__bytes];
const _Bin_record& __bin = _M_bin[__which]; const _Bin_record& __bin = _M_bin[__which];
const _Tune& __options = _M_get_options(); const _Tune& __options = _M_get_options();
char* __c = __p - __options._M_align; char* __c = __p - __options._M_align;
_Block_record* __block = reinterpret_cast<_Block_record*>(__c); _Block_record* __block = reinterpret_cast<_Block_record*>(__c);
if (__gthread_active_p()) if (__gthread_active_p())
{ {
// Calculate the number of records to remove from our freelist: // Calculate the number of records to remove from our freelist:
...@@ -106,38 +273,13 @@ namespace __gnu_cxx ...@@ -106,38 +273,13 @@ namespace __gnu_cxx
__bin._M_first[0] = __block; __bin._M_first[0] = __block;
} }
} }
#endif
void
__pool<false>::_M_reclaim_memory(char* __p, size_t __bytes)
{
// Round up to power of 2 and figure out which bin to use.
const size_t __which = _M_binmap[__bytes];
const _Bin_record& __bin = _M_bin[__which];
const _Tune& __options = _M_get_options();
char* __c = __p - __options._M_align;
_Block_record* __block = reinterpret_cast<_Block_record*>(__c);
// Single threaded application - return to global pool.
__block->_M_next = __bin._M_first[0];
__bin._M_first[0] = __block;
}
#ifdef __GTHREADS
char* char*
__pool<true>::_M_reserve_memory(size_t __bytes, const size_t __thread_id) __pool<true>::_M_reserve_block(size_t __bytes, const size_t __thread_id)
{ {
// Round up to power of 2 and figure out which bin to use. // Round up to power of 2 and figure out which bin to use.
const size_t __which = _M_binmap[__bytes]; const size_t __which = _M_binmap[__bytes];
// If here, there are no blocks on our freelist.
const _Tune& __options = _M_get_options(); const _Tune& __options = _M_get_options();
_Block_record* __block = NULL;
const _Bin_record& __bin = _M_bin[__which];
// NB: For alignment reasons, we can't use the first _M_align
// bytes, even when sizeof(_Block_record) < _M_align.
const size_t __bin_size = ((__options._M_min_bin << __which) const size_t __bin_size = ((__options._M_min_bin << __which)
+ __options._M_align); + __options._M_align);
size_t __block_count = __options._M_chunk_size / __bin_size; size_t __block_count = __options._M_chunk_size / __bin_size;
...@@ -152,19 +294,17 @@ namespace __gnu_cxx ...@@ -152,19 +294,17 @@ namespace __gnu_cxx
// no need to lock or change ownership but check for free // no need to lock or change ownership but check for free
// blocks on global list (and if not add new ones) and // blocks on global list (and if not add new ones) and
// get the first one. // get the first one.
_Bin_record& __bin = _M_bin[__which];
_Block_record* __block = NULL;
if (__gthread_active_p()) if (__gthread_active_p())
{ {
__gthread_mutex_lock(__bin._M_mutex);
if (__bin._M_first[0] == NULL) if (__bin._M_first[0] == NULL)
{ {
// No need to hold the lock when we are adding a // No need to hold the lock when we are adding a whole
// whole chunk to our own list. // chunk to our own list.
__gthread_mutex_unlock(__bin._M_mutex);
void* __v = ::operator new(__options._M_chunk_size); void* __v = ::operator new(__options._M_chunk_size);
__bin._M_first[__thread_id] = static_cast<_Block_record*>(__v); __bin._M_first[__thread_id] = static_cast<_Block_record*>(__v);
__bin._M_free[__thread_id] = __block_count; __bin._M_free[__thread_id] = __block_count;
--__block_count; --__block_count;
__block = __bin._M_first[__thread_id]; __block = __bin._M_first[__thread_id];
while (__block_count-- > 0) while (__block_count-- > 0)
...@@ -174,12 +314,20 @@ namespace __gnu_cxx ...@@ -174,12 +314,20 @@ namespace __gnu_cxx
__block = __block->_M_next; __block = __block->_M_next;
} }
__block->_M_next = NULL; __block->_M_next = NULL;
__gthread_mutex_lock(__bin._M_mutex);
_Block_address* __address = new _Block_address;
__address->_M_initial = __v;
__address->_M_next = __bin._M_address;
__bin._M_address = __address;
__gthread_mutex_unlock(__bin._M_mutex);
} }
else else
{ {
// Is the number of required blocks greater than or // Is the number of required blocks greater than or equal
// equal to the number that can be provided by the // to the number that can be provided by the global free
// global free list? // list?
__gthread_mutex_lock(__bin._M_mutex);
__bin._M_first[__thread_id] = __bin._M_first[0]; __bin._M_first[__thread_id] = __bin._M_first[0];
if (__block_count >= __bin._M_free[0]) if (__block_count >= __bin._M_free[0])
{ {
...@@ -204,10 +352,9 @@ namespace __gnu_cxx ...@@ -204,10 +352,9 @@ namespace __gnu_cxx
else else
{ {
void* __v = ::operator new(__options._M_chunk_size); void* __v = ::operator new(__options._M_chunk_size);
__bin._M_first[0] = static_cast<_Block_record*>(__v); __block = static_cast<_Block_record*>(__v);
__bin._M_first[0] = __block;
--__block_count; --__block_count;
__block = __bin._M_first[0];
while (__block_count-- > 0) while (__block_count-- > 0)
{ {
char* __c = reinterpret_cast<char*>(__block) + __bin_size; char* __c = reinterpret_cast<char*>(__block) + __bin_size;
...@@ -215,6 +362,11 @@ namespace __gnu_cxx ...@@ -215,6 +362,11 @@ namespace __gnu_cxx
__block = __block->_M_next; __block = __block->_M_next;
} }
__block->_M_next = NULL; __block->_M_next = NULL;
_Block_address* __address = new _Block_address;
__address->_M_initial = __v;
__address->_M_next = __bin._M_address;
__bin._M_address = __address;
} }
__block = __bin._M_first[__thread_id]; __block = __bin._M_first[__thread_id];
...@@ -226,53 +378,15 @@ namespace __gnu_cxx ...@@ -226,53 +378,15 @@ namespace __gnu_cxx
--__bin._M_free[__thread_id]; --__bin._M_free[__thread_id];
++__bin._M_used[__thread_id]; ++__bin._M_used[__thread_id];
} }
return reinterpret_cast<char*>(__block) + __options._M_align;
}
#endif
char*
__pool<false>::_M_reserve_memory(size_t __bytes, const size_t __thread_id)
{
// Round up to power of 2 and figure out which bin to use.
const size_t __which = _M_binmap[__bytes];
// If here, there are no blocks on our freelist.
const _Tune& __options = _M_get_options();
_Block_record* __block = NULL;
const _Bin_record& __bin = _M_bin[__which];
// NB: For alignment reasons, we can't use the first _M_align // NB: For alignment reasons, we can't use the first _M_align
// bytes, even when sizeof(_Block_record) < _M_align. // bytes, even when sizeof(_Block_record) < _M_align.
const size_t __bin_size = ((__options._M_min_bin << __which)
+ __options._M_align);
size_t __block_count = __options._M_chunk_size / __bin_size;
// Not using threads.
void* __v = ::operator new(__options._M_chunk_size);
__bin._M_first[0] = static_cast<_Block_record*>(__v);
--__block_count;
__block = __bin._M_first[0];
while (__block_count-- > 0)
{
char* __c = reinterpret_cast<char*>(__block) + __bin_size;
__block->_M_next = reinterpret_cast<_Block_record*>(__c);
__block = __block->_M_next;
}
__block->_M_next = NULL;
__block = __bin._M_first[__thread_id];
__bin._M_first[__thread_id] = __bin._M_first[__thread_id]->_M_next;
return reinterpret_cast<char*>(__block) + __options._M_align; return reinterpret_cast<char*>(__block) + __options._M_align;
} }
#ifdef __GTHREADS
void void
__pool<true>::_M_initialize(__destroy_handler __d) __pool<true>::_M_initialize(__destroy_handler __d)
{ {
// This method is called on the first allocation (when _M_init
// is still false) to create the bins.
// _M_force_new must not change after the first allocate(), // _M_force_new must not change after the first allocate(),
// which in turn calls this method, so if it's false, it's false // which in turn calls this method, so if it's false, it's false
// forever and we don't need to return here ever again. // forever and we don't need to return here ever again.
...@@ -282,6 +396,7 @@ namespace __gnu_cxx ...@@ -282,6 +396,7 @@ namespace __gnu_cxx
return; return;
} }
// Create the bins.
// Calculate the number of bins required based on _M_max_bytes. // Calculate the number of bins required based on _M_max_bytes.
// _M_bin_size is statically-initialized to one. // _M_bin_size is statically-initialized to one.
size_t __bin_size = _M_options._M_min_bin; size_t __bin_size = _M_options._M_min_bin;
...@@ -294,7 +409,6 @@ namespace __gnu_cxx ...@@ -294,7 +409,6 @@ namespace __gnu_cxx
// Setup the bin map for quick lookup of the relevant bin. // Setup the bin map for quick lookup of the relevant bin.
const size_t __j = (_M_options._M_max_bytes + 1) * sizeof(_Binmap_type); const size_t __j = (_M_options._M_max_bytes + 1) * sizeof(_Binmap_type);
_M_binmap = static_cast<_Binmap_type*>(::operator new(__j)); _M_binmap = static_cast<_Binmap_type*>(::operator new(__j));
_Binmap_type* __bp = _M_binmap; _Binmap_type* __bp = _M_binmap;
_Binmap_type __bin_max = _M_options._M_min_bin; _Binmap_type __bin_max = _M_options._M_min_bin;
_Binmap_type __bint = 0; _Binmap_type __bint = 0;
...@@ -320,6 +434,7 @@ namespace __gnu_cxx ...@@ -320,6 +434,7 @@ namespace __gnu_cxx
const size_t __k = sizeof(_Thread_record) * _M_options._M_max_threads; const size_t __k = sizeof(_Thread_record) * _M_options._M_max_threads;
__v = ::operator new(__k); __v = ::operator new(__k);
_M_thread_freelist = static_cast<_Thread_record*>(__v); _M_thread_freelist = static_cast<_Thread_record*>(__v);
_M_thread_freelist_initial = __v;
// NOTE! The first assignable thread id is 1 since the // NOTE! The first assignable thread id is 1 since the
// global pool uses id 0 // global pool uses id 0
...@@ -345,7 +460,9 @@ namespace __gnu_cxx ...@@ -345,7 +460,9 @@ namespace __gnu_cxx
_Bin_record& __bin = _M_bin[__n]; _Bin_record& __bin = _M_bin[__n];
__v = ::operator new(sizeof(_Block_record*) * __max_threads); __v = ::operator new(sizeof(_Block_record*) * __max_threads);
__bin._M_first = static_cast<_Block_record**>(__v); __bin._M_first = static_cast<_Block_record**>(__v);
__bin._M_address = NULL;
__v = ::operator new(sizeof(size_t) * __max_threads); __v = ::operator new(sizeof(size_t) * __max_threads);
__bin._M_free = static_cast<size_t*>(__v); __bin._M_free = static_cast<size_t*>(__v);
...@@ -364,9 +481,7 @@ namespace __gnu_cxx ...@@ -364,9 +481,7 @@ namespace __gnu_cxx
#else #else
{ __GTHREAD_MUTEX_INIT_FUNCTION(__bin._M_mutex); } { __GTHREAD_MUTEX_INIT_FUNCTION(__bin._M_mutex); }
#endif #endif
for (size_t __threadn = 0; __threadn < __max_threads; ++__threadn)
for (size_t __threadn = 0; __threadn < __max_threads;
++__threadn)
{ {
__bin._M_first[__threadn] = NULL; __bin._M_first[__threadn] = NULL;
__bin._M_free[__threadn] = 0; __bin._M_free[__threadn] = 0;
...@@ -375,73 +490,19 @@ namespace __gnu_cxx ...@@ -375,73 +490,19 @@ namespace __gnu_cxx
} }
} }
else else
for (size_t __n = 0; __n < _M_bin_size; ++__n)
{
_Bin_record& __bin = _M_bin[__n];
__v = ::operator new(sizeof(_Block_record*));
__bin._M_first = static_cast<_Block_record**>(__v);
__bin._M_first[0] = NULL;
}
_M_init = true;
}
#endif
void
__pool<false>::_M_initialize()
{
// This method is called on the first allocation (when _M_init
// is still false) to create the bins.
// _M_force_new must not change after the first allocate(),
// which in turn calls this method, so if it's false, it's false
// forever and we don't need to return here ever again.
if (_M_options._M_force_new)
{
_M_init = true;
return;
}
// Calculate the number of bins required based on _M_max_bytes.
// _M_bin_size is statically-initialized to one.
size_t __bin_size = _M_options._M_min_bin;
while (_M_options._M_max_bytes > __bin_size)
{
__bin_size <<= 1;
++_M_bin_size;
}
// Setup the bin map for quick lookup of the relevant bin.
const size_t __j = (_M_options._M_max_bytes + 1) * sizeof(_Binmap_type);
_M_binmap = static_cast<_Binmap_type*>(::operator new(__j));
_Binmap_type* __bp = _M_binmap;
_Binmap_type __bin_max = _M_options._M_min_bin;
_Binmap_type __bint = 0;
for (_Binmap_type __ct = 0; __ct <= _M_options._M_max_bytes; ++__ct)
{ {
if (__ct > __bin_max) for (size_t __n = 0; __n < _M_bin_size; ++__n)
{ {
__bin_max <<= 1; _Bin_record& __bin = _M_bin[__n];
++__bint; __v = ::operator new(sizeof(_Block_record*));
__bin._M_first = static_cast<_Block_record**>(__v);
__bin._M_first[0] = NULL;
__bin._M_address = NULL;
} }
*__bp++ = __bint;
}
// Initialize _M_bin and its members.
void* __v = ::operator new(sizeof(_Bin_record) * _M_bin_size);
_M_bin = static_cast<_Bin_record*>(__v);
for (size_t __n = 0; __n < _M_bin_size; ++__n)
{
_Bin_record& __bin = _M_bin[__n];
__v = ::operator new(sizeof(_Block_record*));
__bin._M_first = static_cast<_Block_record**>(__v);
__bin._M_first[0] = NULL;
} }
_M_init = true; _M_init = true;
} }
#ifdef __GTHREADS
size_t size_t
__pool<true>::_M_get_thread_id() __pool<true>::_M_get_thread_id()
{ {
...@@ -486,23 +547,6 @@ namespace __gnu_cxx ...@@ -486,23 +547,6 @@ namespace __gnu_cxx
} }
#endif #endif
// Definitions for non-exported bits of __common_pool.
#ifdef __GTHREADS
__pool<true>
__common_pool_policy<true>::_S_data = __pool<true>();
__pool<true>&
__common_pool_policy<true>::_S_get_pool() { return _S_data; }
#endif
template<>
__pool<false>
__common_pool_policy<false>::_S_data = __pool<false>();
template<>
__pool<false>&
__common_pool_policy<false>::_S_get_pool() { return _S_data; }
// Instantiations. // Instantiations.
template class __mt_alloc<char>; template class __mt_alloc<char>;
template class __mt_alloc<wchar_t>; template class __mt_alloc<wchar_t>;
......
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/malloc_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::runtime_error("count isn't zero");
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::malloc_allocator<char_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
string_t s("bayou bend");
int main()
{
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <ext/malloc_allocator.h>
#include <testsuite_hooks.h>
static size_t alloc_cnt;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
alloc_cnt++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
alloc_cnt--;
if (alloc_cnt == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", alloc_cnt);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::malloc_allocator<char_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
int main()
{
bool test __attribute__((unused)) = true;
{
string_t s;
s += "bayou bend";
}
VERIFY( alloc_cnt == 0 );
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/mt_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::runtime_error("count isn't zero");
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::__common_pool_policy<true> pool_t;
typedef __gnu_cxx::__mt_alloc<char_t, pool_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
string_t s("bayou bend");
int main()
{
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/mt_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::exception();
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::__common_pool_policy<false> pool_t;
typedef __gnu_cxx::__mt_alloc<char_t, pool_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
string_t s("bayou bend");
int main()
{
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/mt_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::runtime_error("count isn't zero");
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::__per_type_pool_policy<char_t, true> pool_t;
typedef __gnu_cxx::__mt_alloc<char_t, pool_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
string_t s("bayou bend");
int main()
{
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/mt_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::runtime_error("count isn't zero");
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::__per_type_pool_policy<char_t, false> pool_t;
typedef __gnu_cxx::__mt_alloc<char_t, pool_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
string_t s("bayou bend");
int main()
{
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/mt_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::runtime_error("count isn't zero");
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::__common_pool_policy<true> pool_t;
typedef __gnu_cxx::__mt_alloc<char_t, pool_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
int main()
{
bool test __attribute__((unused)) = true;
{
string_t s;
s += "bayou bend";
}
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/mt_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::runtime_error("count isn't zero");
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::__common_pool_policy<false> pool_t;
typedef __gnu_cxx::__mt_alloc<char_t, pool_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
int main()
{
bool test __attribute__((unused)) = true;
{
string_t s;
s += "bayou bend";
}
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/mt_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::runtime_error("count isn't zero");
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::__per_type_pool_policy<char_t, true> pool_t;
typedef __gnu_cxx::__mt_alloc<char_t, pool_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
int main()
{
bool test __attribute__((unused)) = true;
{
string_t s;
s += "bayou bend";
}
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/mt_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::runtime_error("count isn't zero");
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::__per_type_pool_policy<char_t, false> pool_t;
typedef __gnu_cxx::__mt_alloc<char_t, pool_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
int main()
{
bool test __attribute__((unused)) = true;
{
string_t s;
s += "bayou bend";
}
return 0;
}
...@@ -25,4 +25,9 @@ ...@@ -25,4 +25,9 @@
#include <cstdlib> #include <cstdlib>
#include <ext/mt_allocator.h> #include <ext/mt_allocator.h>
template class __gnu_cxx::__mt_alloc<int>; using namespace __gnu_cxx;
template class __mt_alloc<int>;
template class __mt_alloc<short, __common_pool_policy<true> >;
template class __mt_alloc<short, __common_pool_policy<false> >;
template class __mt_alloc<short, __per_type_pool_policy<short, true> >;
template class __mt_alloc<short, __per_type_pool_policy<short, false> >;
// 2001-11-25 Phil Edwards <pme@gcc.gnu.org>
//
// Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <cstdlib>
#include <ext/new_allocator.h>
#include <testsuite_allocator.h>
using __gnu_cxx::new_allocator;
void*
operator new(std::size_t n) throw(std::bad_alloc)
{
new_called = true;
requested = n;
return std::malloc(n);
}
void
operator delete(void *v) throw()
{
delete_called = true;
return std::free(v);
}
// These just help tracking down error messages.
bool test01()
{
typedef new_allocator<unsigned int> allocator_type;
return (__gnu_test::check_new<allocator_type, true>() == true);
}
int main()
{
return test01();
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <stdexcept>
#include <ext/new_allocator.h>
#include <testsuite_hooks.h>
static size_t count;
struct count_check
{
count_check() {}
~count_check()
{
if (count != 0)
throw std::runtime_error("count isn't zero");
}
};
static count_check check;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
count++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
count--;
if (count == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", count);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::new_allocator<char_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
string_t s("bayou bend");
int main()
{
return 0;
}
//
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <string>
#include <ext/new_allocator.h>
#include <testsuite_hooks.h>
static size_t alloc_cnt;
void* operator new(size_t size) throw(std::bad_alloc)
{
printf("operator new is called \n");
void* p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
alloc_cnt++;
return p;
}
void operator delete(void* p) throw()
{
printf("operator delete is called \n");
if (p == NULL)
return;
alloc_cnt--;
if (alloc_cnt == 0)
printf("All memory released \n");
else
printf("%u allocations to be released \n", alloc_cnt);
free(p);
}
typedef char char_t;
typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::new_allocator<char_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
int main()
{
bool test __attribute__((unused)) = true;
{
string_t s;
s += "bayou bend";
}
VERIFY( alloc_cnt == 0 );
return 0;
}
// { dg-do compile }
// 2001-11-25 Phil Edwards <pme@gcc.gnu.org>
//
// Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING. If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
// 20.4.1.1 allocator members
#include <cstdlib>
#include <ext/new_allocator.h>
template class __gnu_cxx::new_allocator<int>;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment