From 12cde21b1201cee86d4fd2c87aa8f40fb09b667e Mon Sep 17 00:00:00 2001 From: Benjamin Kosnik Date: Wed, 6 Oct 2004 04:22:42 +0000 Subject: [PATCH] re PR libstdc++/17780 (std::allocator vs. static init) 2004-10-05 Benjamin Kosnik 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): 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 --- libstdc++-v3/ChangeLog | 41 ++ libstdc++-v3/config/linker-map.gnu | 6 +- libstdc++-v3/include/ext/mt_allocator.h | 199 ++++++---- libstdc++-v3/src/mt_allocator.cc | 372 ++++++++++-------- .../ext/malloc_allocator/deallocate_global.cc | 74 ++++ .../ext/malloc_allocator/deallocate_local.cc | 65 +++ .../ext/mt_allocator/deallocate_global-1.cc | 75 ++++ .../ext/mt_allocator/deallocate_global-2.cc | 75 ++++ .../ext/mt_allocator/deallocate_global-3.cc | 75 ++++ .../ext/mt_allocator/deallocate_global-4.cc | 75 ++++ .../ext/mt_allocator/deallocate_local-1.cc | 78 ++++ .../ext/mt_allocator/deallocate_local-2.cc | 78 ++++ .../ext/mt_allocator/deallocate_local-3.cc | 78 ++++ .../ext/mt_allocator/deallocate_local-4.cc | 78 ++++ .../testsuite/ext/mt_allocator/instantiate.cc | 7 +- .../testsuite/ext/new_allocator/check_new.cc | 55 +++ .../ext/new_allocator/deallocate_global.cc | 74 ++++ .../ext/new_allocator/deallocate_local.cc | 65 +++ .../ext/new_allocator/instantiate.cc | 28 ++ 19 files changed, 1351 insertions(+), 247 deletions(-) create mode 100644 libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_global.cc create mode 100644 libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_local.cc create mode 100644 libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-1.cc create mode 100644 libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-2.cc create mode 100644 libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-3.cc create mode 100644 libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-4.cc create mode 100644 libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-1.cc create mode 100644 libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-2.cc create mode 100644 libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-3.cc create mode 100644 libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-4.cc create mode 100644 libstdc++-v3/testsuite/ext/new_allocator/check_new.cc create mode 100644 libstdc++-v3/testsuite/ext/new_allocator/deallocate_global.cc create mode 100644 libstdc++-v3/testsuite/ext/new_allocator/deallocate_local.cc create mode 100644 libstdc++-v3/testsuite/ext/new_allocator/instantiate.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a7a9964025b..e26f127670e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,44 @@ +2004-10-05 Benjamin Kosnik + + 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): 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 * configure.host (abi_baseline_pair): Define for s390-*-linux* and diff --git a/libstdc++-v3/config/linker-map.gnu b/libstdc++-v3/config/linker-map.gnu index e3c5861ebf7..f6861c87b6f 100644 --- a/libstdc++-v3/config/linker-map.gnu +++ b/libstdc++-v3/config/linker-map.gnu @@ -267,9 +267,9 @@ GLIBCXX_3.4.3 { _ZN9__gnu_cxx6__poolILb1EE13_M_initializeEPFvPvE; _ZN9__gnu_cxx6__poolILb1EE21_M_destroy_thread_keyEPv; _ZN9__gnu_cxx6__poolILb1EE16_M_get_thread_idEv; - _ZN9__gnu_cxx6__poolILb[01]EE17_M_reserve_memoryE[jm][jm]; - _ZN9__gnu_cxx6__poolILb[01]EE17_M_reclaim_memoryEPc[jm]; - _ZN9__gnu_cxx20__common_pool_policyILb[01]EE11_S_get_poolEv; + _ZN9__gnu_cxx6__poolILb[01]EE16_M_reserve_blockE[jm][jm]; + _ZN9__gnu_cxx6__poolILb[01]EE16_M_reclaim_blockEPc[jm]; + _ZN9__gnu_cxx6__poolILb[01]EED[12]Ev; # stub functions from libmath acosf; diff --git a/libstdc++-v3/include/ext/mt_allocator.h b/libstdc++-v3/include/ext/mt_allocator.h index 58ac9e014db..f377d4071c7 100644 --- a/libstdc++-v3/include/ext/mt_allocator.h +++ b/libstdc++-v3/include/ext/mt_allocator.h @@ -56,17 +56,28 @@ namespace __gnu_cxx typedef void (*__destroy_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, // assigned and explained in detail below. 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. // NB: In any case must be >= sizeof(_Block_record), that // 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 // this value will be handled by the allocator. A raw new/ @@ -75,14 +86,14 @@ namespace __gnu_cxx // Size in bytes of the smallest bin. // 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 // new() calls we always request new memory using this // value. Based on previous discussions on the libstdc++ // mailing list we have choosen the value below. // 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 // single-threaded operation, use one. Maximum values will @@ -105,9 +116,9 @@ namespace __gnu_cxx explicit _Tune() - : _M_align(8), _M_max_bytes(128), _M_min_bin(8), - _M_chunk_size(4096 - 4 * sizeof(void*)), - _M_max_threads(4096), _M_freelist_headroom(10), + : _M_align(_S_align), _M_max_bytes(_S_max_bytes), _M_min_bin(_S_min_bin), + _M_chunk_size(_S_chunk_size), _M_max_threads(_S_max_threads), + _M_freelist_headroom(_S_freelist_headroom), _M_force_new(getenv("GLIBCXX_FORCE_NEW") ? true : false) { } @@ -118,6 +129,25 @@ namespace __gnu_cxx _M_chunk_size(__chunk), _M_max_threads(__maxthreads), _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& @@ -140,20 +170,17 @@ namespace __gnu_cxx { return _M_binmap[__bytes]; } explicit __pool_base() - : _M_init(false), _M_options(_Tune()), _M_binmap(NULL) { } + : _M_options(_Tune()), _M_binmap(NULL), _M_init(false) { } 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. _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; + + // 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 @@ -204,10 +231,13 @@ namespace __gnu_cxx struct _Bin_record { // An "array" of pointers to the first free block for each - // thread id. Memory to this "array" is allocated in _S_initialize() - // for _S_max_threads + global pool 0. + // thread id. Memory to this "array" is allocated in + // _S_initialize() for _S_max_threads + global pool 0. _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 // blocks that are on the freelist/used for each thread id. // Memory to these "arrays" is allocated in _S_initialize() for @@ -242,10 +272,10 @@ namespace __gnu_cxx } char* - _M_reserve_memory(size_t __bytes, const size_t __thread_id); + _M_reserve_block(size_t __bytes, const size_t __thread_id); void - _M_reclaim_memory(char* __p, size_t __bytes); + _M_reclaim_block(char* __p, size_t __bytes); const _Bin_record& _M_get_bin(size_t __which) @@ -277,6 +307,8 @@ namespace __gnu_cxx _M_once = __tmp; } + ~__pool(); + private: // An "array" of bin_records each of which represents a specific // power of 2 size. Memory to this "array" is allocated in @@ -289,6 +321,7 @@ namespace __gnu_cxx __gthread_once_t _M_once; _Thread_record* _M_thread_freelist; + void* _M_thread_freelist_initial; }; #endif @@ -302,13 +335,14 @@ namespace __gnu_cxx // Points to the block_record of the next free block. _Block_record* volatile _M_next; }; - + struct _Bin_record { - // An "array" of pointers to the first free block for each - // thread id. Memory to this "array" is allocated in _S_initialize() - // for _S_max_threads + global pool 0. + // An "array" of pointers to the first free block. _Block_record** volatile _M_first; + + // A list of the initial addresses of all allocated blocks. + _Block_address* _M_address; }; void @@ -319,10 +353,10 @@ namespace __gnu_cxx } char* - _M_reserve_memory(size_t __bytes, const size_t __thread_id); + _M_reserve_block(size_t __bytes, const size_t __thread_id); void - _M_reclaim_memory(char* __p, size_t __bytes); + _M_reclaim_block(char* __p, size_t __bytes); size_t _M_get_thread_id() { return 0; } @@ -337,7 +371,9 @@ namespace __gnu_cxx explicit __pool() : _M_bin(NULL), _M_bin_size(1) { } - + + ~__pool(); + private: // An "array" of bin_records each of which represents a specific // power of 2 size. Memory to this "array" is allocated in @@ -351,10 +387,11 @@ namespace __gnu_cxx _M_initialize(); }; - template struct __common_pool_policy { + typedef __pool<_Thread> __pool_type; + template struct _M_rebind; @@ -366,11 +403,12 @@ namespace __gnu_cxx struct _M_rebind<_Tp1, false> { typedef __common_pool_policy other; }; - typedef __pool<_Thread> __pool_type; - static __pool_type _S_data; - static __pool_type& - _S_get_pool(); + _S_get_pool() + { + static __pool_type _S_pool; + return _S_pool; + } static void _S_initialize_once() @@ -391,6 +429,8 @@ namespace __gnu_cxx template<> struct __common_pool_policy { + typedef __pool __pool_type; + template struct _M_rebind; @@ -402,11 +442,12 @@ namespace __gnu_cxx struct _M_rebind<_Tp1, false> { typedef __common_pool_policy other; }; - typedef __pool __pool_type; - static __pool_type _S_data; - static __pool_type& - _S_get_pool(); + _S_get_pool() + { + static __pool_type _S_pool; + return _S_pool; + } static void _S_destroy_thread_key(void* __freelist_pos) @@ -429,9 +470,12 @@ namespace __gnu_cxx }; #endif + template struct __per_type_pool_policy { + typedef __pool<_Thread> __pool_type; + template struct _M_rebind; @@ -443,11 +487,13 @@ namespace __gnu_cxx struct _M_rebind<_Tp1, true> { typedef __per_type_pool_policy<_Tp1, true> other; }; - typedef __pool<_Thread> __pool_type; - static __pool_type _S_data; - + // Avoid static initialization ordering issues. static __pool_type& - _S_get_pool( ) { return _S_data; } + _S_get_pool() + { + static __pool_type _S_pool; + return _S_pool; + } static void _S_initialize_once() @@ -461,10 +507,6 @@ namespace __gnu_cxx } }; - template - __pool<_Thread> - __per_type_pool_policy<_Tp, _Thread>::_S_data; - template struct __per_type_pool_policy<_Tp, true>; @@ -472,6 +514,8 @@ namespace __gnu_cxx template struct __per_type_pool_policy<_Tp, true> { + typedef __pool __pool_type; + template struct _M_rebind; @@ -483,11 +527,13 @@ namespace __gnu_cxx struct _M_rebind<_Tp1, true> { typedef __per_type_pool_policy<_Tp1, true> other; }; - typedef __pool __pool_type; - static __pool_type _S_data; - + // Avoid static initialization ordering issues. static __pool_type& - _S_get_pool( ) { return _S_data; } + _S_get_pool( ) + { + static __pool_type _S_pool; + return _S_pool; + } static void _S_destroy_thread_key(void* __freelist_pos) @@ -508,16 +554,6 @@ namespace __gnu_cxx } } }; - - template - __pool - __per_type_pool_policy<_Tp, true>::_S_data; -#endif - -#ifdef __GTHREADS - typedef __common_pool_policy __default_policy; -#else - typedef __common_pool_policy __default_policy; #endif template @@ -554,8 +590,14 @@ namespace __gnu_cxx destroy(pointer __p) { __p->~_Tp(); } }; +#ifdef __GTHREADS +#define __default_policy __common_pool_policy +#else +#define __default_policy __common_pool_policy +#endif + template - class __mt_alloc : public __mt_alloc_base<_Tp>, _Poolp + class __mt_alloc : public __mt_alloc_base<_Tp>, _Poolp { public: typedef size_t size_type; @@ -575,21 +617,18 @@ namespace __gnu_cxx 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() - { - // XXX - } + { __policy_type::_S_get_pool(); } __mt_alloc(const __mt_alloc&) throw() - { - // XXX - } + { __policy_type::_S_get_pool(); } template __mt_alloc(const __mt_alloc<_Tp1, _Poolp1>& obj) throw() - { - // XXX - } + { __policy_type::_S_get_pool(); } ~__mt_alloc() throw() { } @@ -620,23 +659,23 @@ namespace __gnu_cxx // Requests larger than _M_max_bytes are handled by new/delete // directly. - __pool_type& __pl = this->_S_get_pool(); + __pool_type& __pool = this->_S_get_pool(); const size_t __bytes = __n * sizeof(_Tp); - if (__pl._M_check_threshold(__bytes)) + if (__pool._M_check_threshold(__bytes)) { void* __ret = ::operator new(__bytes); return static_cast<_Tp*>(__ret); } // 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 __thread_id = __pl._M_get_thread_id(); + const size_t __which = __pool._M_get_binmap(__bytes); + const size_t __thread_id = __pool._M_get_thread_id(); // Find out if we have blocks on our freelist. If so, go ahead // and use them directly without having to lock anything. char* __c; 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]) { // Already reserved. @@ -644,14 +683,14 @@ namespace __gnu_cxx _Block_record* __block = __bin._M_first[__thread_id]; __bin._M_first[__thread_id] = __bin._M_first[__thread_id]->_M_next; - __pl._M_adjust_freelist(__bin, __block, __thread_id); - const __pool_base::_Tune& __options = __pl._M_get_options(); + __pool._M_adjust_freelist(__bin, __block, __thread_id); + const __pool_base::_Tune& __options = __pool._M_get_options(); __c = reinterpret_cast(__block) + __options._M_align; } else { // Null, reserve. - __c = __pl._M_reserve_memory(__bytes, __thread_id); + __c = __pool._M_reserve_block(__bytes, __thread_id); } return static_cast<_Tp*>(static_cast(__c)); } @@ -663,12 +702,12 @@ namespace __gnu_cxx { // Requests larger than _M_max_bytes are handled by operators // new/delete directly. - __pool_type& __pl = this->_S_get_pool(); + __pool_type& __pool = this->_S_get_pool(); const size_t __bytes = __n * sizeof(_Tp); - if (__pl._M_check_threshold(__bytes)) + if (__pool._M_check_threshold(__bytes)) ::operator delete(__p); else - __pl._M_reclaim_memory(reinterpret_cast(__p), __bytes); + __pool._M_reclaim_block(reinterpret_cast(__p), __bytes); } template @@ -680,6 +719,8 @@ namespace __gnu_cxx inline bool operator!=(const __mt_alloc<_Tp, _Poolp>&, const __mt_alloc<_Tp, _Poolp>&) { return false; } + +#undef __default_policy } // namespace __gnu_cxx #endif diff --git a/libstdc++-v3/src/mt_allocator.cc b/libstdc++-v3/src/mt_allocator.cc index ab3778c37f6..066726b0367 100644 --- a/libstdc++-v3/src/mt_allocator.cc +++ b/libstdc++-v3/src/mt_allocator.cc @@ -32,8 +32,8 @@ // #include -#include #include +#include namespace __gnu_internal { @@ -46,18 +46,185 @@ namespace __gnu_internal namespace __gnu_cxx { -#ifdef __GTHREADS + __pool::~__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::_M_reclaim_memory(char* __p, size_t __bytes) + __pool::_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::_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(__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(__block) + __options._M_align; + } + + void + __pool::_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 + __pool::~__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 + __pool::_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]; 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); - if (__gthread_active_p()) { // Calculate the number of records to remove from our freelist: @@ -106,38 +273,13 @@ namespace __gnu_cxx __bin._M_first[0] = __block; } } -#endif - void - __pool::_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* - __pool::_M_reserve_memory(size_t __bytes, const size_t __thread_id) + __pool::_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]; - - // 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 - // 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; @@ -152,19 +294,17 @@ namespace __gnu_cxx // no need to lock or change ownership but check for free // blocks on global list (and if not add new ones) and // get the first one. + _Bin_record& __bin = _M_bin[__which]; + _Block_record* __block = NULL; if (__gthread_active_p()) { - __gthread_mutex_lock(__bin._M_mutex); if (__bin._M_first[0] == NULL) { - // No need to hold the lock when we are adding a - // whole chunk to our own list. - __gthread_mutex_unlock(__bin._M_mutex); - + // No need to hold the lock when we are adding a whole + // chunk to our own list. void* __v = ::operator new(__options._M_chunk_size); __bin._M_first[__thread_id] = static_cast<_Block_record*>(__v); __bin._M_free[__thread_id] = __block_count; - --__block_count; __block = __bin._M_first[__thread_id]; while (__block_count-- > 0) @@ -174,12 +314,20 @@ namespace __gnu_cxx __block = __block->_M_next; } __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 { - // Is the number of required blocks greater than or - // equal to the number that can be provided by the - // global free list? + // Is the number of required blocks greater than or equal + // to the number that can be provided by the global free + // list? + __gthread_mutex_lock(__bin._M_mutex); __bin._M_first[__thread_id] = __bin._M_first[0]; if (__block_count >= __bin._M_free[0]) { @@ -204,10 +352,9 @@ namespace __gnu_cxx else { 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 = __bin._M_first[0]; while (__block_count-- > 0) { char* __c = reinterpret_cast(__block) + __bin_size; @@ -215,6 +362,11 @@ namespace __gnu_cxx __block = __block->_M_next; } __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]; @@ -226,53 +378,15 @@ namespace __gnu_cxx --__bin._M_free[__thread_id]; ++__bin._M_used[__thread_id]; } - return reinterpret_cast(__block) + __options._M_align; - } -#endif - char* - __pool::_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 // 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(__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(__block) + __options._M_align; } -#ifdef __GTHREADS void __pool::_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(), // 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. @@ -282,6 +396,7 @@ namespace __gnu_cxx 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; @@ -294,7 +409,6 @@ namespace __gnu_cxx // 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; @@ -320,6 +434,7 @@ namespace __gnu_cxx const size_t __k = sizeof(_Thread_record) * _M_options._M_max_threads; __v = ::operator new(__k); _M_thread_freelist = static_cast<_Thread_record*>(__v); + _M_thread_freelist_initial = __v; // NOTE! The first assignable thread id is 1 since the // global pool uses id 0 @@ -345,7 +460,9 @@ namespace __gnu_cxx _Bin_record& __bin = _M_bin[__n]; __v = ::operator new(sizeof(_Block_record*) * __max_threads); __bin._M_first = static_cast<_Block_record**>(__v); - + + __bin._M_address = NULL; + __v = ::operator new(sizeof(size_t) * __max_threads); __bin._M_free = static_cast(__v); @@ -364,9 +481,7 @@ namespace __gnu_cxx #else { __GTHREAD_MUTEX_INIT_FUNCTION(__bin._M_mutex); } #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_free[__threadn] = 0; @@ -375,73 +490,19 @@ namespace __gnu_cxx } } 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::_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; - ++__bint; + _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; } - *__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; } - -#ifdef __GTHREADS + size_t __pool::_M_get_thread_id() { @@ -486,23 +547,6 @@ namespace __gnu_cxx } #endif - // Definitions for non-exported bits of __common_pool. -#ifdef __GTHREADS - __pool - __common_pool_policy::_S_data = __pool(); - - __pool& - __common_pool_policy::_S_get_pool() { return _S_data; } -#endif - - template<> - __pool - __common_pool_policy::_S_data = __pool(); - - template<> - __pool& - __common_pool_policy::_S_get_pool() { return _S_data; } - // Instantiations. template class __mt_alloc; template class __mt_alloc; diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_global.cc b/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_global.cc new file mode 100644 index 00000000000..4b462bf0e04 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_global.cc @@ -0,0 +1,74 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::malloc_allocator allocator_t; +typedef std::basic_string string_t; + +string_t s("bayou bend"); + +int main() +{ + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_local.cc b/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_local.cc new file mode 100644 index 00000000000..69cbb383a0d --- /dev/null +++ b/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_local.cc @@ -0,0 +1,65 @@ +// +// 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 +#include +#include + +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 traits_t; +typedef __gnu_cxx::malloc_allocator allocator_t; +typedef std::basic_string string_t; + +int main() +{ + bool test __attribute__((unused)) = true; + { + string_t s; + s += "bayou bend"; + } + VERIFY( alloc_cnt == 0 ); + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-1.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-1.cc new file mode 100644 index 00000000000..1f0ac281af7 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-1.cc @@ -0,0 +1,75 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::__common_pool_policy pool_t; +typedef __gnu_cxx::__mt_alloc allocator_t; +typedef std::basic_string string_t; + +string_t s("bayou bend"); + +int main() +{ + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-2.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-2.cc new file mode 100644 index 00000000000..f0484872989 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-2.cc @@ -0,0 +1,75 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::__common_pool_policy pool_t; +typedef __gnu_cxx::__mt_alloc allocator_t; +typedef std::basic_string string_t; + +string_t s("bayou bend"); + +int main() +{ + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-3.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-3.cc new file mode 100644 index 00000000000..10efea66ec6 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-3.cc @@ -0,0 +1,75 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::__per_type_pool_policy pool_t; +typedef __gnu_cxx::__mt_alloc allocator_t; +typedef std::basic_string string_t; + +string_t s("bayou bend"); + +int main() +{ + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-4.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-4.cc new file mode 100644 index 00000000000..02c6a4c4c68 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-4.cc @@ -0,0 +1,75 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::__per_type_pool_policy pool_t; +typedef __gnu_cxx::__mt_alloc allocator_t; +typedef std::basic_string string_t; + +string_t s("bayou bend"); + +int main() +{ + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-1.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-1.cc new file mode 100644 index 00000000000..5664d3caff8 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-1.cc @@ -0,0 +1,78 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::__common_pool_policy pool_t; +typedef __gnu_cxx::__mt_alloc allocator_t; +typedef std::basic_string string_t; + +int main() +{ + bool test __attribute__((unused)) = true; + { + string_t s; + s += "bayou bend"; + } + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-2.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-2.cc new file mode 100644 index 00000000000..a6af89f11f0 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-2.cc @@ -0,0 +1,78 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::__common_pool_policy pool_t; +typedef __gnu_cxx::__mt_alloc allocator_t; +typedef std::basic_string string_t; + +int main() +{ + bool test __attribute__((unused)) = true; + { + string_t s; + s += "bayou bend"; + } + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-3.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-3.cc new file mode 100644 index 00000000000..973f758d98d --- /dev/null +++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-3.cc @@ -0,0 +1,78 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::__per_type_pool_policy pool_t; +typedef __gnu_cxx::__mt_alloc allocator_t; +typedef std::basic_string string_t; + +int main() +{ + bool test __attribute__((unused)) = true; + { + string_t s; + s += "bayou bend"; + } + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-4.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-4.cc new file mode 100644 index 00000000000..c194b977d57 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-4.cc @@ -0,0 +1,78 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::__per_type_pool_policy pool_t; +typedef __gnu_cxx::__mt_alloc allocator_t; +typedef std::basic_string string_t; + +int main() +{ + bool test __attribute__((unused)) = true; + { + string_t s; + s += "bayou bend"; + } + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/instantiate.cc b/libstdc++-v3/testsuite/ext/mt_allocator/instantiate.cc index 8e16b92df39..579b8bcf18d 100644 --- a/libstdc++-v3/testsuite/ext/mt_allocator/instantiate.cc +++ b/libstdc++-v3/testsuite/ext/mt_allocator/instantiate.cc @@ -25,4 +25,9 @@ #include #include -template class __gnu_cxx::__mt_alloc; +using namespace __gnu_cxx; +template class __mt_alloc; +template class __mt_alloc >; +template class __mt_alloc >; +template class __mt_alloc >; +template class __mt_alloc >; diff --git a/libstdc++-v3/testsuite/ext/new_allocator/check_new.cc b/libstdc++-v3/testsuite/ext/new_allocator/check_new.cc new file mode 100644 index 00000000000..e2be5743fdb --- /dev/null +++ b/libstdc++-v3/testsuite/ext/new_allocator/check_new.cc @@ -0,0 +1,55 @@ +// 2001-11-25 Phil Edwards +// +// 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 +#include +#include + +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 allocator_type; + return (__gnu_test::check_new() == true); +} + +int main() +{ + return test01(); +} + diff --git a/libstdc++-v3/testsuite/ext/new_allocator/deallocate_global.cc b/libstdc++-v3/testsuite/ext/new_allocator/deallocate_global.cc new file mode 100644 index 00000000000..6f1451dccf2 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/new_allocator/deallocate_global.cc @@ -0,0 +1,74 @@ +// +// 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 +#include +#include +#include + +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 traits_t; +typedef __gnu_cxx::new_allocator allocator_t; +typedef std::basic_string string_t; + +string_t s("bayou bend"); + +int main() +{ + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/new_allocator/deallocate_local.cc b/libstdc++-v3/testsuite/ext/new_allocator/deallocate_local.cc new file mode 100644 index 00000000000..bc934c6f9ee --- /dev/null +++ b/libstdc++-v3/testsuite/ext/new_allocator/deallocate_local.cc @@ -0,0 +1,65 @@ +// +// 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 +#include +#include + +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 traits_t; +typedef __gnu_cxx::new_allocator allocator_t; +typedef std::basic_string string_t; + +int main() +{ + bool test __attribute__((unused)) = true; + { + string_t s; + s += "bayou bend"; + } + VERIFY( alloc_cnt == 0 ); + return 0; +} diff --git a/libstdc++-v3/testsuite/ext/new_allocator/instantiate.cc b/libstdc++-v3/testsuite/ext/new_allocator/instantiate.cc new file mode 100644 index 00000000000..45bd988f315 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/new_allocator/instantiate.cc @@ -0,0 +1,28 @@ +// { dg-do compile } + +// 2001-11-25 Phil Edwards +// +// 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 +#include + +template class __gnu_cxx::new_allocator;