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