1ffeaf689SAlexander Kabaev // MT-optimized allocator -*- C++ -*- 2ffeaf689SAlexander Kabaev 3f8a1b7d9SAlexander Kabaev // Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 4ffeaf689SAlexander Kabaev // 5ffeaf689SAlexander Kabaev // This file is part of the GNU ISO C++ Library. This library is free 6ffeaf689SAlexander Kabaev // software; you can redistribute it and/or modify it under the 7ffeaf689SAlexander Kabaev // terms of the GNU General Public License as published by the 8ffeaf689SAlexander Kabaev // Free Software Foundation; either version 2, or (at your option) 9ffeaf689SAlexander Kabaev // any later version. 10ffeaf689SAlexander Kabaev 11ffeaf689SAlexander Kabaev // This library is distributed in the hope that it will be useful, 12ffeaf689SAlexander Kabaev // but WITHOUT ANY WARRANTY; without even the implied warranty of 13ffeaf689SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14ffeaf689SAlexander Kabaev // GNU General Public License for more details. 15ffeaf689SAlexander Kabaev 16ffeaf689SAlexander Kabaev // You should have received a copy of the GNU General Public License along 17ffeaf689SAlexander Kabaev // with this library; see the file COPYING. If not, write to the Free 18f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19ffeaf689SAlexander Kabaev // USA. 20ffeaf689SAlexander Kabaev 21ffeaf689SAlexander Kabaev // As a special exception, you may use this file as part of a free software 22ffeaf689SAlexander Kabaev // library without restriction. Specifically, if other files instantiate 23ffeaf689SAlexander Kabaev // templates or use macros or inline functions from this file, or you compile 24ffeaf689SAlexander Kabaev // this file and link it with other files to produce an executable, this 25ffeaf689SAlexander Kabaev // file does not by itself cause the resulting executable to be covered by 26ffeaf689SAlexander Kabaev // the GNU General Public License. This exception does not however 27ffeaf689SAlexander Kabaev // invalidate any other reasons why the executable file might be covered by 28ffeaf689SAlexander Kabaev // the GNU General Public License. 29ffeaf689SAlexander Kabaev 30ffeaf689SAlexander Kabaev /** @file ext/mt_allocator.h 31ffeaf689SAlexander Kabaev * This file is a GNU extension to the Standard C++ Library. 32ffeaf689SAlexander Kabaev */ 33ffeaf689SAlexander Kabaev 34ffeaf689SAlexander Kabaev #ifndef _MT_ALLOCATOR_H 35ffeaf689SAlexander Kabaev #define _MT_ALLOCATOR_H 1 36ffeaf689SAlexander Kabaev 37ffeaf689SAlexander Kabaev #include <new> 38ffeaf689SAlexander Kabaev #include <cstdlib> 39ffeaf689SAlexander Kabaev #include <bits/functexcept.h> 40f8a1b7d9SAlexander Kabaev #include <ext/atomicity.h> 41ffeaf689SAlexander Kabaev 42f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 43f8a1b7d9SAlexander Kabaev 44f8a1b7d9SAlexander Kabaev using std::size_t; 45f8a1b7d9SAlexander Kabaev using std::ptrdiff_t; 46f8a1b7d9SAlexander Kabaev 47f8a1b7d9SAlexander Kabaev typedef void (*__destroy_handler)(void*); 48f8a1b7d9SAlexander Kabaev 49f8a1b7d9SAlexander Kabaev /// @brief Base class for pool object. 50f8a1b7d9SAlexander Kabaev struct __pool_base 51ffeaf689SAlexander Kabaev { 52f8a1b7d9SAlexander Kabaev // Using short int as type for the binmap implies we are never 53f8a1b7d9SAlexander Kabaev // caching blocks larger than 32768 with this allocator. 54f8a1b7d9SAlexander Kabaev typedef unsigned short int _Binmap_type; 55f8a1b7d9SAlexander Kabaev 56f8a1b7d9SAlexander Kabaev // Variables used to configure the behavior of the allocator, 57f8a1b7d9SAlexander Kabaev // assigned and explained in detail below. 58f8a1b7d9SAlexander Kabaev struct _Tune 59f8a1b7d9SAlexander Kabaev { 60f8a1b7d9SAlexander Kabaev // Compile time constants for the default _Tune values. 61f8a1b7d9SAlexander Kabaev enum { _S_align = 8 }; 62f8a1b7d9SAlexander Kabaev enum { _S_max_bytes = 128 }; 63f8a1b7d9SAlexander Kabaev enum { _S_min_bin = 8 }; 64f8a1b7d9SAlexander Kabaev enum { _S_chunk_size = 4096 - 4 * sizeof(void*) }; 65f8a1b7d9SAlexander Kabaev enum { _S_max_threads = 4096 }; 66f8a1b7d9SAlexander Kabaev enum { _S_freelist_headroom = 10 }; 67f8a1b7d9SAlexander Kabaev 68f8a1b7d9SAlexander Kabaev // Alignment needed. 69f8a1b7d9SAlexander Kabaev // NB: In any case must be >= sizeof(_Block_record), that 70f8a1b7d9SAlexander Kabaev // is 4 on 32 bit machines and 8 on 64 bit machines. 71f8a1b7d9SAlexander Kabaev size_t _M_align; 72f8a1b7d9SAlexander Kabaev 73f8a1b7d9SAlexander Kabaev // Allocation requests (after round-up to power of 2) below 74f8a1b7d9SAlexander Kabaev // this value will be handled by the allocator. A raw new/ 75f8a1b7d9SAlexander Kabaev // call will be used for requests larger than this value. 76f8a1b7d9SAlexander Kabaev // NB: Must be much smaller than _M_chunk_size and in any 77f8a1b7d9SAlexander Kabaev // case <= 32768. 78f8a1b7d9SAlexander Kabaev size_t _M_max_bytes; 79f8a1b7d9SAlexander Kabaev 80f8a1b7d9SAlexander Kabaev // Size in bytes of the smallest bin. 81f8a1b7d9SAlexander Kabaev // NB: Must be a power of 2 and >= _M_align (and of course 82f8a1b7d9SAlexander Kabaev // much smaller than _M_max_bytes). 83f8a1b7d9SAlexander Kabaev size_t _M_min_bin; 84f8a1b7d9SAlexander Kabaev 85f8a1b7d9SAlexander Kabaev // In order to avoid fragmenting and minimize the number of 86f8a1b7d9SAlexander Kabaev // new() calls we always request new memory using this 87f8a1b7d9SAlexander Kabaev // value. Based on previous discussions on the libstdc++ 88f8a1b7d9SAlexander Kabaev // mailing list we have choosen the value below. 89f8a1b7d9SAlexander Kabaev // See http://gcc.gnu.org/ml/libstdc++/2001-07/msg00077.html 90f8a1b7d9SAlexander Kabaev // NB: At least one order of magnitude > _M_max_bytes. 91f8a1b7d9SAlexander Kabaev size_t _M_chunk_size; 92f8a1b7d9SAlexander Kabaev 93f8a1b7d9SAlexander Kabaev // The maximum number of supported threads. For 94f8a1b7d9SAlexander Kabaev // single-threaded operation, use one. Maximum values will 95f8a1b7d9SAlexander Kabaev // vary depending on details of the underlying system. (For 96f8a1b7d9SAlexander Kabaev // instance, Linux 2.4.18 reports 4070 in 97f8a1b7d9SAlexander Kabaev // /proc/sys/kernel/threads-max, while Linux 2.6.6 reports 98f8a1b7d9SAlexander Kabaev // 65534) 99f8a1b7d9SAlexander Kabaev size_t _M_max_threads; 100f8a1b7d9SAlexander Kabaev 101f8a1b7d9SAlexander Kabaev // Each time a deallocation occurs in a threaded application 102f8a1b7d9SAlexander Kabaev // we make sure that there are no more than 103f8a1b7d9SAlexander Kabaev // _M_freelist_headroom % of used memory on the freelist. If 104f8a1b7d9SAlexander Kabaev // the number of additional records is more than 105f8a1b7d9SAlexander Kabaev // _M_freelist_headroom % of the freelist, we move these 106f8a1b7d9SAlexander Kabaev // records back to the global pool. 107f8a1b7d9SAlexander Kabaev size_t _M_freelist_headroom; 108f8a1b7d9SAlexander Kabaev 109f8a1b7d9SAlexander Kabaev // Set to true forces all allocations to use new(). 110f8a1b7d9SAlexander Kabaev bool _M_force_new; 111f8a1b7d9SAlexander Kabaev 112f8a1b7d9SAlexander Kabaev explicit _Tune__pool_base::_Tune113f8a1b7d9SAlexander Kabaev _Tune() 114f8a1b7d9SAlexander Kabaev : _M_align(_S_align), _M_max_bytes(_S_max_bytes), _M_min_bin(_S_min_bin), 115f8a1b7d9SAlexander Kabaev _M_chunk_size(_S_chunk_size), _M_max_threads(_S_max_threads), 116f8a1b7d9SAlexander Kabaev _M_freelist_headroom(_S_freelist_headroom), 117f8a1b7d9SAlexander Kabaev _M_force_new(std::getenv("GLIBCXX_FORCE_NEW") ? true : false) 118f8a1b7d9SAlexander Kabaev { } 119f8a1b7d9SAlexander Kabaev 120f8a1b7d9SAlexander Kabaev explicit _Tune__pool_base::_Tune121f8a1b7d9SAlexander Kabaev _Tune(size_t __align, size_t __maxb, size_t __minbin, size_t __chunk, 122f8a1b7d9SAlexander Kabaev size_t __maxthreads, size_t __headroom, bool __force) 123f8a1b7d9SAlexander Kabaev : _M_align(__align), _M_max_bytes(__maxb), _M_min_bin(__minbin), 124f8a1b7d9SAlexander Kabaev _M_chunk_size(__chunk), _M_max_threads(__maxthreads), 125f8a1b7d9SAlexander Kabaev _M_freelist_headroom(__headroom), _M_force_new(__force) 126f8a1b7d9SAlexander Kabaev { } 127f8a1b7d9SAlexander Kabaev }; 128f8a1b7d9SAlexander Kabaev 129f8a1b7d9SAlexander Kabaev struct _Block_address 130f8a1b7d9SAlexander Kabaev { 131f8a1b7d9SAlexander Kabaev void* _M_initial; 132f8a1b7d9SAlexander Kabaev _Block_address* _M_next; 133f8a1b7d9SAlexander Kabaev }; 134f8a1b7d9SAlexander Kabaev 135f8a1b7d9SAlexander Kabaev const _Tune& _M_get_options__pool_base136f8a1b7d9SAlexander Kabaev _M_get_options() const 137f8a1b7d9SAlexander Kabaev { return _M_options; } 138f8a1b7d9SAlexander Kabaev 139f8a1b7d9SAlexander Kabaev void _M_set_options__pool_base140f8a1b7d9SAlexander Kabaev _M_set_options(_Tune __t) 141f8a1b7d9SAlexander Kabaev { 142f8a1b7d9SAlexander Kabaev if (!_M_init) 143f8a1b7d9SAlexander Kabaev _M_options = __t; 144f8a1b7d9SAlexander Kabaev } 145f8a1b7d9SAlexander Kabaev 146f8a1b7d9SAlexander Kabaev bool _M_check_threshold__pool_base147f8a1b7d9SAlexander Kabaev _M_check_threshold(size_t __bytes) 148f8a1b7d9SAlexander Kabaev { return __bytes > _M_options._M_max_bytes || _M_options._M_force_new; } 149f8a1b7d9SAlexander Kabaev 150f8a1b7d9SAlexander Kabaev size_t _M_get_binmap__pool_base151f8a1b7d9SAlexander Kabaev _M_get_binmap(size_t __bytes) 152f8a1b7d9SAlexander Kabaev { return _M_binmap[__bytes]; } 153f8a1b7d9SAlexander Kabaev 154f8a1b7d9SAlexander Kabaev const size_t _M_get_align__pool_base155f8a1b7d9SAlexander Kabaev _M_get_align() 156f8a1b7d9SAlexander Kabaev { return _M_options._M_align; } 157f8a1b7d9SAlexander Kabaev 158f8a1b7d9SAlexander Kabaev explicit __pool_base__pool_base159f8a1b7d9SAlexander Kabaev __pool_base() 160f8a1b7d9SAlexander Kabaev : _M_options(_Tune()), _M_binmap(NULL), _M_init(false) { } 161f8a1b7d9SAlexander Kabaev 162f8a1b7d9SAlexander Kabaev explicit __pool_base__pool_base163f8a1b7d9SAlexander Kabaev __pool_base(const _Tune& __options) 164f8a1b7d9SAlexander Kabaev : _M_options(__options), _M_binmap(NULL), _M_init(false) { } 165f8a1b7d9SAlexander Kabaev 166f8a1b7d9SAlexander Kabaev private: 167f8a1b7d9SAlexander Kabaev explicit 168f8a1b7d9SAlexander Kabaev __pool_base(const __pool_base&); 169f8a1b7d9SAlexander Kabaev 170f8a1b7d9SAlexander Kabaev __pool_base& 171f8a1b7d9SAlexander Kabaev operator=(const __pool_base&); 172f8a1b7d9SAlexander Kabaev 173f8a1b7d9SAlexander Kabaev protected: 174f8a1b7d9SAlexander Kabaev // Configuration options. 175f8a1b7d9SAlexander Kabaev _Tune _M_options; 176f8a1b7d9SAlexander Kabaev 177f8a1b7d9SAlexander Kabaev _Binmap_type* _M_binmap; 178f8a1b7d9SAlexander Kabaev 179f8a1b7d9SAlexander Kabaev // Configuration of the pool object via _M_options can happen 180f8a1b7d9SAlexander Kabaev // after construction but before initialization. After 181f8a1b7d9SAlexander Kabaev // initialization is complete, this variable is set to true. 182f8a1b7d9SAlexander Kabaev bool _M_init; 183f8a1b7d9SAlexander Kabaev }; 184f8a1b7d9SAlexander Kabaev 185f8a1b7d9SAlexander Kabaev 186ffeaf689SAlexander Kabaev /** 187f8a1b7d9SAlexander Kabaev * @brief Data describing the underlying memory pool, parameterized on 188f8a1b7d9SAlexander Kabaev * threading support. 189ffeaf689SAlexander Kabaev */ 190f8a1b7d9SAlexander Kabaev template<bool _Thread> 191f8a1b7d9SAlexander Kabaev class __pool; 192f8a1b7d9SAlexander Kabaev 193f8a1b7d9SAlexander Kabaev /// Specialization for single thread. 194f8a1b7d9SAlexander Kabaev template<> 195f8a1b7d9SAlexander Kabaev class __pool<false> : public __pool_base 196f8a1b7d9SAlexander Kabaev { 197f8a1b7d9SAlexander Kabaev public: 198f8a1b7d9SAlexander Kabaev union _Block_record 199f8a1b7d9SAlexander Kabaev { 200f8a1b7d9SAlexander Kabaev // Points to the block_record of the next free block. 201f8a1b7d9SAlexander Kabaev _Block_record* _M_next; 202f8a1b7d9SAlexander Kabaev }; 203f8a1b7d9SAlexander Kabaev 204f8a1b7d9SAlexander Kabaev struct _Bin_record 205f8a1b7d9SAlexander Kabaev { 206f8a1b7d9SAlexander Kabaev // An "array" of pointers to the first free block. 207f8a1b7d9SAlexander Kabaev _Block_record** _M_first; 208f8a1b7d9SAlexander Kabaev 209f8a1b7d9SAlexander Kabaev // A list of the initial addresses of all allocated blocks. 210f8a1b7d9SAlexander Kabaev _Block_address* _M_address; 211f8a1b7d9SAlexander Kabaev }; 212f8a1b7d9SAlexander Kabaev 213f8a1b7d9SAlexander Kabaev void _M_initialize_once()214f8a1b7d9SAlexander Kabaev _M_initialize_once() 215f8a1b7d9SAlexander Kabaev { 216f8a1b7d9SAlexander Kabaev if (__builtin_expect(_M_init == false, false)) 217f8a1b7d9SAlexander Kabaev _M_initialize(); 218f8a1b7d9SAlexander Kabaev } 219f8a1b7d9SAlexander Kabaev 220f8a1b7d9SAlexander Kabaev void 221f8a1b7d9SAlexander Kabaev _M_destroy() throw(); 222f8a1b7d9SAlexander Kabaev 223f8a1b7d9SAlexander Kabaev char* 224f8a1b7d9SAlexander Kabaev _M_reserve_block(size_t __bytes, const size_t __thread_id); 225f8a1b7d9SAlexander Kabaev 226f8a1b7d9SAlexander Kabaev void 227f8a1b7d9SAlexander Kabaev _M_reclaim_block(char* __p, size_t __bytes); 228f8a1b7d9SAlexander Kabaev 229f8a1b7d9SAlexander Kabaev size_t _M_get_thread_id()230f8a1b7d9SAlexander Kabaev _M_get_thread_id() { return 0; } 231f8a1b7d9SAlexander Kabaev 232f8a1b7d9SAlexander Kabaev const _Bin_record& _M_get_bin(size_t __which)233f8a1b7d9SAlexander Kabaev _M_get_bin(size_t __which) 234f8a1b7d9SAlexander Kabaev { return _M_bin[__which]; } 235f8a1b7d9SAlexander Kabaev 236f8a1b7d9SAlexander Kabaev void _M_adjust_freelist(const _Bin_record &,_Block_record *,size_t)237f8a1b7d9SAlexander Kabaev _M_adjust_freelist(const _Bin_record&, _Block_record*, size_t) 238f8a1b7d9SAlexander Kabaev { } 239f8a1b7d9SAlexander Kabaev __pool()240f8a1b7d9SAlexander Kabaev explicit __pool() 241f8a1b7d9SAlexander Kabaev : _M_bin(NULL), _M_bin_size(1) { } 242f8a1b7d9SAlexander Kabaev __pool(const __pool_base::_Tune & __tune)243f8a1b7d9SAlexander Kabaev explicit __pool(const __pool_base::_Tune& __tune) 244f8a1b7d9SAlexander Kabaev : __pool_base(__tune), _M_bin(NULL), _M_bin_size(1) { } 245f8a1b7d9SAlexander Kabaev 246f8a1b7d9SAlexander Kabaev private: 247f8a1b7d9SAlexander Kabaev // An "array" of bin_records each of which represents a specific 248f8a1b7d9SAlexander Kabaev // power of 2 size. Memory to this "array" is allocated in 249f8a1b7d9SAlexander Kabaev // _M_initialize(). 250f8a1b7d9SAlexander Kabaev _Bin_record* _M_bin; 251f8a1b7d9SAlexander Kabaev 252f8a1b7d9SAlexander Kabaev // Actual value calculated in _M_initialize(). 253f8a1b7d9SAlexander Kabaev size_t _M_bin_size; 254f8a1b7d9SAlexander Kabaev 255f8a1b7d9SAlexander Kabaev void 256f8a1b7d9SAlexander Kabaev _M_initialize(); 257f8a1b7d9SAlexander Kabaev }; 258f8a1b7d9SAlexander Kabaev 259f8a1b7d9SAlexander Kabaev #ifdef __GTHREADS 260f8a1b7d9SAlexander Kabaev /// Specialization for thread enabled, via gthreads.h. 261f8a1b7d9SAlexander Kabaev template<> 262f8a1b7d9SAlexander Kabaev class __pool<true> : public __pool_base 263f8a1b7d9SAlexander Kabaev { 264f8a1b7d9SAlexander Kabaev public: 265f8a1b7d9SAlexander Kabaev // Each requesting thread is assigned an id ranging from 1 to 266f8a1b7d9SAlexander Kabaev // _S_max_threads. Thread id 0 is used as a global memory pool. 267f8a1b7d9SAlexander Kabaev // In order to get constant performance on the thread assignment 268f8a1b7d9SAlexander Kabaev // routine, we keep a list of free ids. When a thread first 269f8a1b7d9SAlexander Kabaev // requests memory we remove the first record in this list and 270f8a1b7d9SAlexander Kabaev // stores the address in a __gthread_key. When initializing the 271f8a1b7d9SAlexander Kabaev // __gthread_key we specify a destructor. When this destructor 272f8a1b7d9SAlexander Kabaev // (i.e. the thread dies) is called, we return the thread id to 273f8a1b7d9SAlexander Kabaev // the front of this list. 274f8a1b7d9SAlexander Kabaev struct _Thread_record 275f8a1b7d9SAlexander Kabaev { 276f8a1b7d9SAlexander Kabaev // Points to next free thread id record. NULL if last record in list. 277f8a1b7d9SAlexander Kabaev _Thread_record* _M_next; 278f8a1b7d9SAlexander Kabaev 279f8a1b7d9SAlexander Kabaev // Thread id ranging from 1 to _S_max_threads. 280f8a1b7d9SAlexander Kabaev size_t _M_id; 281f8a1b7d9SAlexander Kabaev }; 282f8a1b7d9SAlexander Kabaev 283f8a1b7d9SAlexander Kabaev union _Block_record 284f8a1b7d9SAlexander Kabaev { 285f8a1b7d9SAlexander Kabaev // Points to the block_record of the next free block. 286f8a1b7d9SAlexander Kabaev _Block_record* _M_next; 287f8a1b7d9SAlexander Kabaev 288f8a1b7d9SAlexander Kabaev // The thread id of the thread which has requested this block. 289f8a1b7d9SAlexander Kabaev size_t _M_thread_id; 290f8a1b7d9SAlexander Kabaev }; 291f8a1b7d9SAlexander Kabaev 292f8a1b7d9SAlexander Kabaev struct _Bin_record 293f8a1b7d9SAlexander Kabaev { 294f8a1b7d9SAlexander Kabaev // An "array" of pointers to the first free block for each 295f8a1b7d9SAlexander Kabaev // thread id. Memory to this "array" is allocated in 296f8a1b7d9SAlexander Kabaev // _S_initialize() for _S_max_threads + global pool 0. 297f8a1b7d9SAlexander Kabaev _Block_record** _M_first; 298f8a1b7d9SAlexander Kabaev 299f8a1b7d9SAlexander Kabaev // A list of the initial addresses of all allocated blocks. 300f8a1b7d9SAlexander Kabaev _Block_address* _M_address; 301f8a1b7d9SAlexander Kabaev 302f8a1b7d9SAlexander Kabaev // An "array" of counters used to keep track of the amount of 303f8a1b7d9SAlexander Kabaev // blocks that are on the freelist/used for each thread id. 304f8a1b7d9SAlexander Kabaev // - Note that the second part of the allocated _M_used "array" 305f8a1b7d9SAlexander Kabaev // actually hosts (atomic) counters of reclaimed blocks: in 306f8a1b7d9SAlexander Kabaev // _M_reserve_block and in _M_reclaim_block those numbers are 307f8a1b7d9SAlexander Kabaev // subtracted from the first ones to obtain the actual size 308f8a1b7d9SAlexander Kabaev // of the "working set" of the given thread. 309f8a1b7d9SAlexander Kabaev // - Memory to these "arrays" is allocated in _S_initialize() 310f8a1b7d9SAlexander Kabaev // for _S_max_threads + global pool 0. 311f8a1b7d9SAlexander Kabaev size_t* _M_free; 312f8a1b7d9SAlexander Kabaev size_t* _M_used; 313f8a1b7d9SAlexander Kabaev 314f8a1b7d9SAlexander Kabaev // Each bin has its own mutex which is used to ensure data 315f8a1b7d9SAlexander Kabaev // integrity while changing "ownership" on a block. The mutex 316f8a1b7d9SAlexander Kabaev // is initialized in _S_initialize(). 317f8a1b7d9SAlexander Kabaev __gthread_mutex_t* _M_mutex; 318f8a1b7d9SAlexander Kabaev }; 319f8a1b7d9SAlexander Kabaev 320f8a1b7d9SAlexander Kabaev // XXX GLIBCXX_ABI Deprecated 321f8a1b7d9SAlexander Kabaev void 322f8a1b7d9SAlexander Kabaev _M_initialize(__destroy_handler); 323f8a1b7d9SAlexander Kabaev 324f8a1b7d9SAlexander Kabaev void _M_initialize_once()325f8a1b7d9SAlexander Kabaev _M_initialize_once() 326f8a1b7d9SAlexander Kabaev { 327f8a1b7d9SAlexander Kabaev if (__builtin_expect(_M_init == false, false)) 328f8a1b7d9SAlexander Kabaev _M_initialize(); 329f8a1b7d9SAlexander Kabaev } 330f8a1b7d9SAlexander Kabaev 331f8a1b7d9SAlexander Kabaev void 332f8a1b7d9SAlexander Kabaev _M_destroy() throw(); 333f8a1b7d9SAlexander Kabaev 334f8a1b7d9SAlexander Kabaev char* 335f8a1b7d9SAlexander Kabaev _M_reserve_block(size_t __bytes, const size_t __thread_id); 336f8a1b7d9SAlexander Kabaev 337f8a1b7d9SAlexander Kabaev void 338f8a1b7d9SAlexander Kabaev _M_reclaim_block(char* __p, size_t __bytes); 339f8a1b7d9SAlexander Kabaev 340f8a1b7d9SAlexander Kabaev const _Bin_record& _M_get_bin(size_t __which)341f8a1b7d9SAlexander Kabaev _M_get_bin(size_t __which) 342f8a1b7d9SAlexander Kabaev { return _M_bin[__which]; } 343f8a1b7d9SAlexander Kabaev 344f8a1b7d9SAlexander Kabaev void _M_adjust_freelist(const _Bin_record & __bin,_Block_record * __block_record,size_t __thread_id)345*096464d3SPedro F. Giffuni _M_adjust_freelist(const _Bin_record& __bin, _Block_record* __block_record, 346f8a1b7d9SAlexander Kabaev size_t __thread_id) 347f8a1b7d9SAlexander Kabaev { 348f8a1b7d9SAlexander Kabaev if (__gthread_active_p()) 349f8a1b7d9SAlexander Kabaev { 350*096464d3SPedro F. Giffuni __block_record->_M_thread_id = __thread_id; 351f8a1b7d9SAlexander Kabaev --__bin._M_free[__thread_id]; 352f8a1b7d9SAlexander Kabaev ++__bin._M_used[__thread_id]; 353f8a1b7d9SAlexander Kabaev } 354f8a1b7d9SAlexander Kabaev } 355f8a1b7d9SAlexander Kabaev 356f8a1b7d9SAlexander Kabaev // XXX GLIBCXX_ABI Deprecated 357f8a1b7d9SAlexander Kabaev void 358f8a1b7d9SAlexander Kabaev _M_destroy_thread_key(void*); 359f8a1b7d9SAlexander Kabaev 360f8a1b7d9SAlexander Kabaev size_t 361f8a1b7d9SAlexander Kabaev _M_get_thread_id(); 362f8a1b7d9SAlexander Kabaev __pool()363f8a1b7d9SAlexander Kabaev explicit __pool() 364f8a1b7d9SAlexander Kabaev : _M_bin(NULL), _M_bin_size(1), _M_thread_freelist(NULL) 365f8a1b7d9SAlexander Kabaev { } 366f8a1b7d9SAlexander Kabaev __pool(const __pool_base::_Tune & __tune)367f8a1b7d9SAlexander Kabaev explicit __pool(const __pool_base::_Tune& __tune) 368f8a1b7d9SAlexander Kabaev : __pool_base(__tune), _M_bin(NULL), _M_bin_size(1), 369f8a1b7d9SAlexander Kabaev _M_thread_freelist(NULL) 370f8a1b7d9SAlexander Kabaev { } 371f8a1b7d9SAlexander Kabaev 372f8a1b7d9SAlexander Kabaev private: 373f8a1b7d9SAlexander Kabaev // An "array" of bin_records each of which represents a specific 374f8a1b7d9SAlexander Kabaev // power of 2 size. Memory to this "array" is allocated in 375f8a1b7d9SAlexander Kabaev // _M_initialize(). 376f8a1b7d9SAlexander Kabaev _Bin_record* _M_bin; 377f8a1b7d9SAlexander Kabaev 378f8a1b7d9SAlexander Kabaev // Actual value calculated in _M_initialize(). 379f8a1b7d9SAlexander Kabaev size_t _M_bin_size; 380f8a1b7d9SAlexander Kabaev 381f8a1b7d9SAlexander Kabaev _Thread_record* _M_thread_freelist; 382f8a1b7d9SAlexander Kabaev void* _M_thread_freelist_initial; 383f8a1b7d9SAlexander Kabaev 384f8a1b7d9SAlexander Kabaev void 385f8a1b7d9SAlexander Kabaev _M_initialize(); 386f8a1b7d9SAlexander Kabaev }; 387f8a1b7d9SAlexander Kabaev #endif 388f8a1b7d9SAlexander Kabaev 389f8a1b7d9SAlexander Kabaev template<template <bool> class _PoolTp, bool _Thread> 390f8a1b7d9SAlexander Kabaev struct __common_pool 391f8a1b7d9SAlexander Kabaev { 392f8a1b7d9SAlexander Kabaev typedef _PoolTp<_Thread> pool_type; 393f8a1b7d9SAlexander Kabaev 394f8a1b7d9SAlexander Kabaev static pool_type& _S_get_pool__common_pool395f8a1b7d9SAlexander Kabaev _S_get_pool() 396f8a1b7d9SAlexander Kabaev { 397f8a1b7d9SAlexander Kabaev static pool_type _S_pool; 398f8a1b7d9SAlexander Kabaev return _S_pool; 399f8a1b7d9SAlexander Kabaev } 400f8a1b7d9SAlexander Kabaev }; 401f8a1b7d9SAlexander Kabaev 402f8a1b7d9SAlexander Kabaev template<template <bool> class _PoolTp, bool _Thread> 403f8a1b7d9SAlexander Kabaev struct __common_pool_base; 404f8a1b7d9SAlexander Kabaev 405f8a1b7d9SAlexander Kabaev template<template <bool> class _PoolTp> 406f8a1b7d9SAlexander Kabaev struct __common_pool_base<_PoolTp, false> 407f8a1b7d9SAlexander Kabaev : public __common_pool<_PoolTp, false> 408f8a1b7d9SAlexander Kabaev { 409f8a1b7d9SAlexander Kabaev using __common_pool<_PoolTp, false>::_S_get_pool; 410f8a1b7d9SAlexander Kabaev 411f8a1b7d9SAlexander Kabaev static void 412f8a1b7d9SAlexander Kabaev _S_initialize_once() 413f8a1b7d9SAlexander Kabaev { 414f8a1b7d9SAlexander Kabaev static bool __init; 415f8a1b7d9SAlexander Kabaev if (__builtin_expect(__init == false, false)) 416f8a1b7d9SAlexander Kabaev { 417f8a1b7d9SAlexander Kabaev _S_get_pool()._M_initialize_once(); 418f8a1b7d9SAlexander Kabaev __init = true; 419f8a1b7d9SAlexander Kabaev } 420f8a1b7d9SAlexander Kabaev } 421f8a1b7d9SAlexander Kabaev }; 422f8a1b7d9SAlexander Kabaev 423f8a1b7d9SAlexander Kabaev #ifdef __GTHREADS 424f8a1b7d9SAlexander Kabaev template<template <bool> class _PoolTp> 425f8a1b7d9SAlexander Kabaev struct __common_pool_base<_PoolTp, true> 426f8a1b7d9SAlexander Kabaev : public __common_pool<_PoolTp, true> 427f8a1b7d9SAlexander Kabaev { 428f8a1b7d9SAlexander Kabaev using __common_pool<_PoolTp, true>::_S_get_pool; 429f8a1b7d9SAlexander Kabaev 430f8a1b7d9SAlexander Kabaev static void 431f8a1b7d9SAlexander Kabaev _S_initialize() 432f8a1b7d9SAlexander Kabaev { _S_get_pool()._M_initialize_once(); } 433f8a1b7d9SAlexander Kabaev 434f8a1b7d9SAlexander Kabaev static void 435f8a1b7d9SAlexander Kabaev _S_initialize_once() 436f8a1b7d9SAlexander Kabaev { 437f8a1b7d9SAlexander Kabaev static bool __init; 438f8a1b7d9SAlexander Kabaev if (__builtin_expect(__init == false, false)) 439f8a1b7d9SAlexander Kabaev { 440f8a1b7d9SAlexander Kabaev if (__gthread_active_p()) 441f8a1b7d9SAlexander Kabaev { 442f8a1b7d9SAlexander Kabaev // On some platforms, __gthread_once_t is an aggregate. 443f8a1b7d9SAlexander Kabaev static __gthread_once_t __once = __GTHREAD_ONCE_INIT; 444f8a1b7d9SAlexander Kabaev __gthread_once(&__once, _S_initialize); 445f8a1b7d9SAlexander Kabaev } 446f8a1b7d9SAlexander Kabaev 447f8a1b7d9SAlexander Kabaev // Double check initialization. May be necessary on some 448f8a1b7d9SAlexander Kabaev // systems for proper construction when not compiling with 449f8a1b7d9SAlexander Kabaev // thread flags. 450f8a1b7d9SAlexander Kabaev _S_get_pool()._M_initialize_once(); 451f8a1b7d9SAlexander Kabaev __init = true; 452f8a1b7d9SAlexander Kabaev } 453f8a1b7d9SAlexander Kabaev } 454f8a1b7d9SAlexander Kabaev }; 455f8a1b7d9SAlexander Kabaev #endif 456f8a1b7d9SAlexander Kabaev 457f8a1b7d9SAlexander Kabaev /// @brief Policy for shared __pool objects. 458f8a1b7d9SAlexander Kabaev template<template <bool> class _PoolTp, bool _Thread> 459f8a1b7d9SAlexander Kabaev struct __common_pool_policy : public __common_pool_base<_PoolTp, _Thread> 460f8a1b7d9SAlexander Kabaev { 461f8a1b7d9SAlexander Kabaev template<typename _Tp1, template <bool> class _PoolTp1 = _PoolTp, 462f8a1b7d9SAlexander Kabaev bool _Thread1 = _Thread> 463f8a1b7d9SAlexander Kabaev struct _M_rebind 464f8a1b7d9SAlexander Kabaev { typedef __common_pool_policy<_PoolTp1, _Thread1> other; }; 465f8a1b7d9SAlexander Kabaev 466f8a1b7d9SAlexander Kabaev using __common_pool_base<_PoolTp, _Thread>::_S_get_pool; 467f8a1b7d9SAlexander Kabaev using __common_pool_base<_PoolTp, _Thread>::_S_initialize_once; 468f8a1b7d9SAlexander Kabaev }; 469f8a1b7d9SAlexander Kabaev 470f8a1b7d9SAlexander Kabaev 471f8a1b7d9SAlexander Kabaev template<typename _Tp, template <bool> class _PoolTp, bool _Thread> 472f8a1b7d9SAlexander Kabaev struct __per_type_pool 473f8a1b7d9SAlexander Kabaev { 474f8a1b7d9SAlexander Kabaev typedef _Tp value_type; 475f8a1b7d9SAlexander Kabaev typedef _PoolTp<_Thread> pool_type; 476f8a1b7d9SAlexander Kabaev 477f8a1b7d9SAlexander Kabaev static pool_type& 478f8a1b7d9SAlexander Kabaev _S_get_pool() 479f8a1b7d9SAlexander Kabaev { 480f8a1b7d9SAlexander Kabaev // Sane defaults for the _PoolTp. 481f8a1b7d9SAlexander Kabaev typedef typename pool_type::_Block_record _Block_record; 482f8a1b7d9SAlexander Kabaev const static size_t __a = (__alignof__(_Tp) >= sizeof(_Block_record) 483f8a1b7d9SAlexander Kabaev ? __alignof__(_Tp) : sizeof(_Block_record)); 484f8a1b7d9SAlexander Kabaev 485f8a1b7d9SAlexander Kabaev typedef typename __pool_base::_Tune _Tune; 486f8a1b7d9SAlexander Kabaev static _Tune _S_tune(__a, sizeof(_Tp) * 64, 487f8a1b7d9SAlexander Kabaev sizeof(_Tp) * 2 >= __a ? sizeof(_Tp) * 2 : __a, 488f8a1b7d9SAlexander Kabaev sizeof(_Tp) * size_t(_Tune::_S_chunk_size), 489f8a1b7d9SAlexander Kabaev _Tune::_S_max_threads, 490f8a1b7d9SAlexander Kabaev _Tune::_S_freelist_headroom, 491f8a1b7d9SAlexander Kabaev std::getenv("GLIBCXX_FORCE_NEW") ? true : false); 492f8a1b7d9SAlexander Kabaev static pool_type _S_pool(_S_tune); 493f8a1b7d9SAlexander Kabaev return _S_pool; 494f8a1b7d9SAlexander Kabaev } 495f8a1b7d9SAlexander Kabaev }; 496f8a1b7d9SAlexander Kabaev 497f8a1b7d9SAlexander Kabaev template<typename _Tp, template <bool> class _PoolTp, bool _Thread> 498f8a1b7d9SAlexander Kabaev struct __per_type_pool_base; 499f8a1b7d9SAlexander Kabaev 500f8a1b7d9SAlexander Kabaev template<typename _Tp, template <bool> class _PoolTp> 501f8a1b7d9SAlexander Kabaev struct __per_type_pool_base<_Tp, _PoolTp, false> 502f8a1b7d9SAlexander Kabaev : public __per_type_pool<_Tp, _PoolTp, false> 503f8a1b7d9SAlexander Kabaev { 504f8a1b7d9SAlexander Kabaev using __per_type_pool<_Tp, _PoolTp, false>::_S_get_pool; 505f8a1b7d9SAlexander Kabaev 506f8a1b7d9SAlexander Kabaev static void 507f8a1b7d9SAlexander Kabaev _S_initialize_once() 508f8a1b7d9SAlexander Kabaev { 509f8a1b7d9SAlexander Kabaev static bool __init; 510f8a1b7d9SAlexander Kabaev if (__builtin_expect(__init == false, false)) 511f8a1b7d9SAlexander Kabaev { 512f8a1b7d9SAlexander Kabaev _S_get_pool()._M_initialize_once(); 513f8a1b7d9SAlexander Kabaev __init = true; 514f8a1b7d9SAlexander Kabaev } 515f8a1b7d9SAlexander Kabaev } 516f8a1b7d9SAlexander Kabaev }; 517f8a1b7d9SAlexander Kabaev 518f8a1b7d9SAlexander Kabaev #ifdef __GTHREADS 519f8a1b7d9SAlexander Kabaev template<typename _Tp, template <bool> class _PoolTp> 520f8a1b7d9SAlexander Kabaev struct __per_type_pool_base<_Tp, _PoolTp, true> 521f8a1b7d9SAlexander Kabaev : public __per_type_pool<_Tp, _PoolTp, true> 522f8a1b7d9SAlexander Kabaev { 523f8a1b7d9SAlexander Kabaev using __per_type_pool<_Tp, _PoolTp, true>::_S_get_pool; 524f8a1b7d9SAlexander Kabaev 525f8a1b7d9SAlexander Kabaev static void 526f8a1b7d9SAlexander Kabaev _S_initialize() 527f8a1b7d9SAlexander Kabaev { _S_get_pool()._M_initialize_once(); } 528f8a1b7d9SAlexander Kabaev 529f8a1b7d9SAlexander Kabaev static void 530f8a1b7d9SAlexander Kabaev _S_initialize_once() 531f8a1b7d9SAlexander Kabaev { 532f8a1b7d9SAlexander Kabaev static bool __init; 533f8a1b7d9SAlexander Kabaev if (__builtin_expect(__init == false, false)) 534f8a1b7d9SAlexander Kabaev { 535f8a1b7d9SAlexander Kabaev if (__gthread_active_p()) 536f8a1b7d9SAlexander Kabaev { 537f8a1b7d9SAlexander Kabaev // On some platforms, __gthread_once_t is an aggregate. 538f8a1b7d9SAlexander Kabaev static __gthread_once_t __once = __GTHREAD_ONCE_INIT; 539f8a1b7d9SAlexander Kabaev __gthread_once(&__once, _S_initialize); 540f8a1b7d9SAlexander Kabaev } 541f8a1b7d9SAlexander Kabaev 542f8a1b7d9SAlexander Kabaev // Double check initialization. May be necessary on some 543f8a1b7d9SAlexander Kabaev // systems for proper construction when not compiling with 544f8a1b7d9SAlexander Kabaev // thread flags. 545f8a1b7d9SAlexander Kabaev _S_get_pool()._M_initialize_once(); 546f8a1b7d9SAlexander Kabaev __init = true; 547f8a1b7d9SAlexander Kabaev } 548f8a1b7d9SAlexander Kabaev } 549f8a1b7d9SAlexander Kabaev }; 550f8a1b7d9SAlexander Kabaev #endif 551f8a1b7d9SAlexander Kabaev 552f8a1b7d9SAlexander Kabaev /// @brief Policy for individual __pool objects. 553f8a1b7d9SAlexander Kabaev template<typename _Tp, template <bool> class _PoolTp, bool _Thread> 554f8a1b7d9SAlexander Kabaev struct __per_type_pool_policy 555f8a1b7d9SAlexander Kabaev : public __per_type_pool_base<_Tp, _PoolTp, _Thread> 556f8a1b7d9SAlexander Kabaev { 557f8a1b7d9SAlexander Kabaev template<typename _Tp1, template <bool> class _PoolTp1 = _PoolTp, 558f8a1b7d9SAlexander Kabaev bool _Thread1 = _Thread> 559f8a1b7d9SAlexander Kabaev struct _M_rebind 560f8a1b7d9SAlexander Kabaev { typedef __per_type_pool_policy<_Tp1, _PoolTp1, _Thread1> other; }; 561f8a1b7d9SAlexander Kabaev 562f8a1b7d9SAlexander Kabaev using __per_type_pool_base<_Tp, _PoolTp, _Thread>::_S_get_pool; 563f8a1b7d9SAlexander Kabaev using __per_type_pool_base<_Tp, _PoolTp, _Thread>::_S_initialize_once; 564f8a1b7d9SAlexander Kabaev }; 565f8a1b7d9SAlexander Kabaev 566f8a1b7d9SAlexander Kabaev 567f8a1b7d9SAlexander Kabaev /// @brief Base class for _Tp dependent member functions. 568ffeaf689SAlexander Kabaev template<typename _Tp> 569f8a1b7d9SAlexander Kabaev class __mt_alloc_base 570ffeaf689SAlexander Kabaev { 571ffeaf689SAlexander Kabaev public: 572ffeaf689SAlexander Kabaev typedef size_t size_type; 573ffeaf689SAlexander Kabaev typedef ptrdiff_t difference_type; 574ffeaf689SAlexander Kabaev typedef _Tp* pointer; 575ffeaf689SAlexander Kabaev typedef const _Tp* const_pointer; 576ffeaf689SAlexander Kabaev typedef _Tp& reference; 577ffeaf689SAlexander Kabaev typedef const _Tp& const_reference; 578ffeaf689SAlexander Kabaev typedef _Tp value_type; 579ffeaf689SAlexander Kabaev 580ffeaf689SAlexander Kabaev pointer 581ffeaf689SAlexander Kabaev address(reference __x) const 582ffeaf689SAlexander Kabaev { return &__x; } 583ffeaf689SAlexander Kabaev 584ffeaf689SAlexander Kabaev const_pointer 585ffeaf689SAlexander Kabaev address(const_reference __x) const 586ffeaf689SAlexander Kabaev { return &__x; } 587ffeaf689SAlexander Kabaev 588ffeaf689SAlexander Kabaev size_type 589ffeaf689SAlexander Kabaev max_size() const throw() 590ffeaf689SAlexander Kabaev { return size_t(-1) / sizeof(_Tp); } 591ffeaf689SAlexander Kabaev 592ffeaf689SAlexander Kabaev // _GLIBCXX_RESOLVE_LIB_DEFECTS 593ffeaf689SAlexander Kabaev // 402. wrong new expression in [some_] allocator::construct 594ffeaf689SAlexander Kabaev void 595ffeaf689SAlexander Kabaev construct(pointer __p, const _Tp& __val) 596ffeaf689SAlexander Kabaev { ::new(__p) _Tp(__val); } 597ffeaf689SAlexander Kabaev 598ffeaf689SAlexander Kabaev void 599ffeaf689SAlexander Kabaev destroy(pointer __p) { __p->~_Tp(); } 600f8a1b7d9SAlexander Kabaev }; 601f8a1b7d9SAlexander Kabaev 602f8a1b7d9SAlexander Kabaev #ifdef __GTHREADS 603f8a1b7d9SAlexander Kabaev #define __thread_default true 604f8a1b7d9SAlexander Kabaev #else 605f8a1b7d9SAlexander Kabaev #define __thread_default false 606f8a1b7d9SAlexander Kabaev #endif 607f8a1b7d9SAlexander Kabaev 608f8a1b7d9SAlexander Kabaev /** 609f8a1b7d9SAlexander Kabaev * @brief This is a fixed size (power of 2) allocator which - when 610f8a1b7d9SAlexander Kabaev * compiled with thread support - will maintain one freelist per 611f8a1b7d9SAlexander Kabaev * size per thread plus a "global" one. Steps are taken to limit 612f8a1b7d9SAlexander Kabaev * the per thread freelist sizes (by returning excess back to 613f8a1b7d9SAlexander Kabaev * the "global" list). 614f8a1b7d9SAlexander Kabaev * 615f8a1b7d9SAlexander Kabaev * Further details: 616f8a1b7d9SAlexander Kabaev * http://gcc.gnu.org/onlinedocs/libstdc++/ext/mt_allocator.html 617f8a1b7d9SAlexander Kabaev */ 618f8a1b7d9SAlexander Kabaev template<typename _Tp, 619f8a1b7d9SAlexander Kabaev typename _Poolp = __common_pool_policy<__pool, __thread_default> > 620f8a1b7d9SAlexander Kabaev class __mt_alloc : public __mt_alloc_base<_Tp> 621f8a1b7d9SAlexander Kabaev { 622f8a1b7d9SAlexander Kabaev public: 623f8a1b7d9SAlexander Kabaev typedef size_t size_type; 624f8a1b7d9SAlexander Kabaev typedef ptrdiff_t difference_type; 625f8a1b7d9SAlexander Kabaev typedef _Tp* pointer; 626f8a1b7d9SAlexander Kabaev typedef const _Tp* const_pointer; 627f8a1b7d9SAlexander Kabaev typedef _Tp& reference; 628f8a1b7d9SAlexander Kabaev typedef const _Tp& const_reference; 629f8a1b7d9SAlexander Kabaev typedef _Tp value_type; 630f8a1b7d9SAlexander Kabaev typedef _Poolp __policy_type; 631f8a1b7d9SAlexander Kabaev typedef typename _Poolp::pool_type __pool_type; 632f8a1b7d9SAlexander Kabaev 633f8a1b7d9SAlexander Kabaev template<typename _Tp1, typename _Poolp1 = _Poolp> 634f8a1b7d9SAlexander Kabaev struct rebind 635f8a1b7d9SAlexander Kabaev { 636f8a1b7d9SAlexander Kabaev typedef typename _Poolp1::template _M_rebind<_Tp1>::other pol_type; 637f8a1b7d9SAlexander Kabaev typedef __mt_alloc<_Tp1, pol_type> other; 638f8a1b7d9SAlexander Kabaev }; 639f8a1b7d9SAlexander Kabaev 640f8a1b7d9SAlexander Kabaev __mt_alloc() throw() { } 641f8a1b7d9SAlexander Kabaev 642f8a1b7d9SAlexander Kabaev __mt_alloc(const __mt_alloc&) throw() { } 643f8a1b7d9SAlexander Kabaev 644f8a1b7d9SAlexander Kabaev template<typename _Tp1, typename _Poolp1> 645f8a1b7d9SAlexander Kabaev __mt_alloc(const __mt_alloc<_Tp1, _Poolp1>&) throw() { } 646f8a1b7d9SAlexander Kabaev 647f8a1b7d9SAlexander Kabaev ~__mt_alloc() throw() { } 648ffeaf689SAlexander Kabaev 649ffeaf689SAlexander Kabaev pointer 650ffeaf689SAlexander Kabaev allocate(size_type __n, const void* = 0); 651ffeaf689SAlexander Kabaev 652ffeaf689SAlexander Kabaev void 653ffeaf689SAlexander Kabaev deallocate(pointer __p, size_type __n); 654ffeaf689SAlexander Kabaev 655f8a1b7d9SAlexander Kabaev const __pool_base::_Tune 656f8a1b7d9SAlexander Kabaev _M_get_options() 657ffeaf689SAlexander Kabaev { 658f8a1b7d9SAlexander Kabaev // Return a copy, not a reference, for external consumption. 659f8a1b7d9SAlexander Kabaev return __policy_type::_S_get_pool()._M_get_options(); 660ffeaf689SAlexander Kabaev } 661ffeaf689SAlexander Kabaev 662f8a1b7d9SAlexander Kabaev void 663f8a1b7d9SAlexander Kabaev _M_set_options(__pool_base::_Tune __t) 664f8a1b7d9SAlexander Kabaev { __policy_type::_S_get_pool()._M_set_options(__t); } 665ffeaf689SAlexander Kabaev }; 666ffeaf689SAlexander Kabaev 667f8a1b7d9SAlexander Kabaev template<typename _Tp, typename _Poolp> 668f8a1b7d9SAlexander Kabaev typename __mt_alloc<_Tp, _Poolp>::pointer 669f8a1b7d9SAlexander Kabaev __mt_alloc<_Tp, _Poolp>:: 670ffeaf689SAlexander Kabaev allocate(size_type __n, const void*) 671ffeaf689SAlexander Kabaev { 672f8a1b7d9SAlexander Kabaev if (__builtin_expect(__n > this->max_size(), false)) 673f8a1b7d9SAlexander Kabaev std::__throw_bad_alloc(); 674ffeaf689SAlexander Kabaev 675f8a1b7d9SAlexander Kabaev __policy_type::_S_initialize_once(); 676f8a1b7d9SAlexander Kabaev 677f8a1b7d9SAlexander Kabaev // Requests larger than _M_max_bytes are handled by operator 678f8a1b7d9SAlexander Kabaev // new/delete directly. 679f8a1b7d9SAlexander Kabaev __pool_type& __pool = __policy_type::_S_get_pool(); 680ffeaf689SAlexander Kabaev const size_t __bytes = __n * sizeof(_Tp); 681f8a1b7d9SAlexander Kabaev if (__pool._M_check_threshold(__bytes)) 682ffeaf689SAlexander Kabaev { 683ffeaf689SAlexander Kabaev void* __ret = ::operator new(__bytes); 684ffeaf689SAlexander Kabaev return static_cast<_Tp*>(__ret); 685ffeaf689SAlexander Kabaev } 686ffeaf689SAlexander Kabaev 687ffeaf689SAlexander Kabaev // Round up to power of 2 and figure out which bin to use. 688f8a1b7d9SAlexander Kabaev const size_t __which = __pool._M_get_binmap(__bytes); 689f8a1b7d9SAlexander Kabaev const size_t __thread_id = __pool._M_get_thread_id(); 690ffeaf689SAlexander Kabaev 691ffeaf689SAlexander Kabaev // Find out if we have blocks on our freelist. If so, go ahead 692ffeaf689SAlexander Kabaev // and use them directly without having to lock anything. 693f8a1b7d9SAlexander Kabaev char* __c; 694f8a1b7d9SAlexander Kabaev typedef typename __pool_type::_Bin_record _Bin_record; 695f8a1b7d9SAlexander Kabaev const _Bin_record& __bin = __pool._M_get_bin(__which); 696f8a1b7d9SAlexander Kabaev if (__bin._M_first[__thread_id]) 697ffeaf689SAlexander Kabaev { 698f8a1b7d9SAlexander Kabaev // Already reserved. 699f8a1b7d9SAlexander Kabaev typedef typename __pool_type::_Block_record _Block_record; 700*096464d3SPedro F. Giffuni _Block_record* __block_record = __bin._M_first[__thread_id]; 701*096464d3SPedro F. Giffuni __bin._M_first[__thread_id] = __block_record->_M_next; 702ffeaf689SAlexander Kabaev 703*096464d3SPedro F. Giffuni __pool._M_adjust_freelist(__bin, __block_record, __thread_id); 704*096464d3SPedro F. Giffuni __c = reinterpret_cast<char*>(__block_record) + __pool._M_get_align(); 705ffeaf689SAlexander Kabaev } 706ffeaf689SAlexander Kabaev else 707ffeaf689SAlexander Kabaev { 708f8a1b7d9SAlexander Kabaev // Null, reserve. 709f8a1b7d9SAlexander Kabaev __c = __pool._M_reserve_block(__bytes, __thread_id); 710ffeaf689SAlexander Kabaev } 711ffeaf689SAlexander Kabaev return static_cast<_Tp*>(static_cast<void*>(__c)); 712ffeaf689SAlexander Kabaev } 713ffeaf689SAlexander Kabaev 714f8a1b7d9SAlexander Kabaev template<typename _Tp, typename _Poolp> 715ffeaf689SAlexander Kabaev void 716f8a1b7d9SAlexander Kabaev __mt_alloc<_Tp, _Poolp>:: 717ffeaf689SAlexander Kabaev deallocate(pointer __p, size_type __n) 718ffeaf689SAlexander Kabaev { 719f8a1b7d9SAlexander Kabaev if (__builtin_expect(__p != 0, true)) 720f8a1b7d9SAlexander Kabaev { 721f8a1b7d9SAlexander Kabaev // Requests larger than _M_max_bytes are handled by 722f8a1b7d9SAlexander Kabaev // operators new/delete directly. 723f8a1b7d9SAlexander Kabaev __pool_type& __pool = __policy_type::_S_get_pool(); 724ffeaf689SAlexander Kabaev const size_t __bytes = __n * sizeof(_Tp); 725f8a1b7d9SAlexander Kabaev if (__pool._M_check_threshold(__bytes)) 726ffeaf689SAlexander Kabaev ::operator delete(__p); 727ffeaf689SAlexander Kabaev else 728f8a1b7d9SAlexander Kabaev __pool._M_reclaim_block(reinterpret_cast<char*>(__p), __bytes); 729ffeaf689SAlexander Kabaev } 730ffeaf689SAlexander Kabaev } 731ffeaf689SAlexander Kabaev 732f8a1b7d9SAlexander Kabaev template<typename _Tp, typename _Poolp> 733ffeaf689SAlexander Kabaev inline bool 734f8a1b7d9SAlexander Kabaev operator==(const __mt_alloc<_Tp, _Poolp>&, const __mt_alloc<_Tp, _Poolp>&) 735ffeaf689SAlexander Kabaev { return true; } 736ffeaf689SAlexander Kabaev 737f8a1b7d9SAlexander Kabaev template<typename _Tp, typename _Poolp> 738ffeaf689SAlexander Kabaev inline bool 739f8a1b7d9SAlexander Kabaev operator!=(const __mt_alloc<_Tp, _Poolp>&, const __mt_alloc<_Tp, _Poolp>&) 740ffeaf689SAlexander Kabaev { return false; } 741ffeaf689SAlexander Kabaev 742f8a1b7d9SAlexander Kabaev #undef __thread_default 743ffeaf689SAlexander Kabaev 744f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NAMESPACE 745ffeaf689SAlexander Kabaev 746ffeaf689SAlexander Kabaev #endif 747