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