1 // Allocators -*- C++ -*-
3 // Copyright (C) 2001 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
31 * Copyright (c) 1996-1997
32 * Silicon Graphics Computer Systems, Inc.
34 * Permission to use, copy, modify, distribute and sell this software
35 * and its documentation for any purpose is hereby granted without fee,
36 * provided that the above copyright notice appear in all copies and
37 * that both that copyright notice and this permission notice appear
38 * in supporting documentation. Silicon Graphics makes no
39 * representations about the suitability of this software for any
40 * purpose. It is provided "as is" without express or implied warranty.
44 * This is an internal header file, included by other library headers.
45 * You should not attempt to use it directly.
48 #ifndef __SGI_STL_INTERNAL_ALLOC_H
49 #define __SGI_STL_INTERNAL_ALLOC_H
51 // This header implements some node allocators. These are NOT the same as
52 // allocators in the C++ standard, nor in the original HP STL. They do not
53 // encapsulate different pointer types; we assume that there is only one
54 // pointer type. The C++ standard allocators are intended to allocate
55 // individual objects, not pools or arenas.
57 // In this file allocators are of two different styles: "standard" and
58 // "SGI" (quotes included). "Standard" allocators conform to 20.4. "SGI"
59 // allocators differ in AT LEAST the following ways (add to this list as you
62 // - "Standard" allocate() takes two parameters (n_count,hint=0) but "SGI"
63 // allocate() takes one paramter (n_size).
64 // - Likewise, "standard" deallocate()'s n is a count, but in "SGI" is a
66 // - max_size(), construct(), and destroy() are missing in "SGI" allocators.
67 // - reallocate(p,oldsz,newsz) is added in "SGI", and behaves as
68 // if p=realloc(p,newsz).
71 #include <bits/functexcept.h> // for __throw_bad_alloc
72 #include <bits/std_cstddef.h>
73 #include <bits/std_cstdlib.h>
74 #include <bits/std_cstring.h>
75 #include <bits/std_cassert.h>
77 // To see the effects of this block of macro wrangling, jump to
78 // "Default node allocator" below.
80 # include <bits/stl_threads.h>
81 # define __NODE_ALLOCATOR_THREADS true
82 # ifdef __STL_SGI_THREADS
83 // We test whether threads are in use before locking.
84 // Perhaps this should be moved into stl_threads.h, but that
85 // probably makes it harder to avoid the procedure call when
88 extern int __us_rsthread_malloc;
90 // The above is copied from malloc.h. Including <malloc.h>
91 // would be cleaner but fails with certain levels of standard
93 # define __NODE_ALLOCATOR_LOCK if (__threads && __us_rsthread_malloc) \
94 { _S_node_allocator_lock._M_acquire_lock(); }
95 # define __NODE_ALLOCATOR_UNLOCK if (__threads && __us_rsthread_malloc) \
96 { _S_node_allocator_lock._M_release_lock(); }
97 # else /* !__STL_SGI_THREADS */
98 # define __NODE_ALLOCATOR_LOCK \
99 { if (__threads) _S_node_allocator_lock._M_acquire_lock(); }
100 # define __NODE_ALLOCATOR_UNLOCK \
101 { if (__threads) _S_node_allocator_lock._M_release_lock(); }
105 # define __NODE_ALLOCATOR_LOCK
106 # define __NODE_ALLOCATOR_UNLOCK
107 # define __NODE_ALLOCATOR_THREADS false
114 * A new-based allocator, as required by the standard. Allocation and
115 * deallocation forward to global new and delete. "SGI" style, minus
124 { return ::operator new(__n); }
127 deallocate(void* __p, size_t)
128 { ::operator delete(__p); }
134 * A malloc-based allocator. Typically slower than the
135 * __default_alloc_template (below). Typically thread-safe and more
136 * storage efficient. The template argument is unused and is only present
137 * to permit multiple instantiations (but see __default_alloc_template
138 * for caveats). "SGI" style, plus __set_malloc_handler for OOM conditions.
141 template <int __inst>
142 class __malloc_alloc_template
145 static void* _S_oom_malloc(size_t);
146 static void* _S_oom_realloc(void*, size_t);
147 static void (* __malloc_alloc_oom_handler)();
153 void* __result = malloc(__n);
154 if (0 == __result) __result = _S_oom_malloc(__n);
159 deallocate(void* __p, size_t /* __n */)
163 reallocate(void* __p, size_t /* old_sz */, size_t __new_sz)
165 void* __result = realloc(__p, __new_sz);
166 if (0 == __result) __result = _S_oom_realloc(__p, __new_sz);
170 static void (* __set_malloc_handler(void (*__f)()))()
172 void (* __old)() = __malloc_alloc_oom_handler;
173 __malloc_alloc_oom_handler = __f;
178 // malloc_alloc out-of-memory handling
179 template <int __inst>
180 void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0;
182 template <int __inst>
184 __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
186 void (* __my_malloc_handler)();
191 __my_malloc_handler = __malloc_alloc_oom_handler;
192 if (0 == __my_malloc_handler)
193 std::__throw_bad_alloc();
194 (*__my_malloc_handler)();
195 __result = malloc(__n);
201 template <int __inst>
203 __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n)
205 void (* __my_malloc_handler)();
210 __my_malloc_handler = __malloc_alloc_oom_handler;
211 if (0 == __my_malloc_handler)
212 std::__throw_bad_alloc();
213 (*__my_malloc_handler)();
214 __result = realloc(__p, __n);
221 // Determines the underlying allocator choice for the node allocator.
223 typedef __malloc_alloc_template<0> __mem_interface;
225 typedef __new_alloc __mem_interface;
230 * This is used primarily (only?) in _Alloc_traits and other places to
231 * help provide the _Alloc_type typedef.
233 * This is neither "standard"-conforming nor "SGI". The _Alloc parameter
234 * must be "SGI" style.
236 template<class _Tp, class _Alloc>
240 static _Tp* allocate(size_t __n)
241 { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
243 static _Tp* allocate()
244 { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }
246 static void deallocate(_Tp* __p, size_t __n)
247 { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }
249 static void deallocate(_Tp* __p)
250 { _Alloc::deallocate(__p, sizeof (_Tp)); }
255 * An adaptor for an underlying allocator (_Alloc) to check the size
256 * arguments for debugging. Errors are reported using assert; these
257 * checks can be disabled via NDEBUG, but the space penalty is still
258 * paid, therefore it is far better to just use the underlying allocator
259 * by itelf when no checking is desired.
261 * "There is some evidence that this can confuse Purify." - SGI comment
263 * This adaptor is "SGI" style. The _Alloc parameter must also be "SGI".
265 template <class _Alloc>
269 enum {_S_extra = 8}; // Size of space used to store size. Note that this
270 // must be large enough to preserve alignment.
274 static void* allocate(size_t __n)
276 char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra);
277 *(size_t*)__result = __n;
278 return __result + (int) _S_extra;
281 static void deallocate(void* __p, size_t __n)
283 char* __real_p = (char*)__p - (int) _S_extra;
284 assert(*(size_t*)__real_p == __n);
285 _Alloc::deallocate(__real_p, __n + (int) _S_extra);
288 static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz)
290 char* __real_p = (char*)__p - (int) _S_extra;
291 assert(*(size_t*)__real_p == __old_sz);
292 char* __result = (char*)
293 _Alloc::reallocate(__real_p, __old_sz + (int) _S_extra,
294 __new_sz + (int) _S_extra);
295 *(size_t*)__result = __new_sz;
296 return __result + (int) _S_extra;
303 typedef __mem_interface alloc;
304 typedef __mem_interface single_client_alloc;
311 * Default node allocator.
313 * Important implementation properties:
314 * 1. If the clients request an object of size > _MAX_BYTES, the resulting
315 * object will be obtained directly from malloc.
316 * 2. In all other cases, we allocate an object of size exactly
317 * _S_round_up(requested_size). Thus the client has enough size
318 * information that we can return the object to the proper free list
319 * without permanently losing part of the object.
321 * The first template parameter specifies whether more than one thread may
322 * use this allocator. It is safe to allocate an object from one instance
323 * of a default_alloc and deallocate it with another one. This effectively
324 * transfers its ownership to the second one. This may have undesirable
325 * effects on reference locality.
327 * The second parameter is unused and serves only to allow the creation of
328 * multiple default_alloc instances. Note that containers built on different
329 * allocator instances have different types, limiting the utility of this
330 * approach. If you do not wish to share the free lists with the main
331 * default_alloc instance, instantiate this with a non-zero __inst.
334 template <bool __threads, int __inst>
335 class __default_alloc_template
340 enum {_MAX_BYTES = 128};
341 enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN
344 _S_round_up(size_t __bytes)
345 { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); }
348 union _Obj* _M_free_list_link;
349 char _M_client_data[1]; // The client sees this.
352 static _Obj* volatile _S_free_list[];
353 static size_t _S_freelist_index(size_t __bytes)
354 { return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1); }
356 // Returns an object of size __n, and optionally adds to size __n free list.
357 static void* _S_refill(size_t __n);
358 // Allocates a chunk for nobjs of size size. nobjs may be reduced
359 // if it is inconvenient to allocate the requested number.
360 static char* _S_chunk_alloc(size_t __size, int& __nobjs);
362 // Chunk allocation state.
363 static char* _S_start_free;
364 static char* _S_end_free;
365 static size_t _S_heap_size;
368 static _STL_mutex_lock _S_node_allocator_lock;
371 // It would be nice to use _STL_auto_lock here. But we
372 // don't need the NULL check. And we do need a test whether
373 // threads have actually been started.
378 _Lock() { __NODE_ALLOCATOR_LOCK; }
379 ~_Lock() { __NODE_ALLOCATOR_UNLOCK; }
385 static void* allocate(size_t __n)
389 if (__n > (size_t) _MAX_BYTES)
390 __ret = __mem_interface::allocate(__n);
393 _Obj* volatile* __my_free_list = _S_free_list + _S_freelist_index(__n);
394 // Acquire the lock here with a constructor call.
395 // This ensures that it is released in exit or during stack
399 _Lock __lock_instance;
401 _Obj* __restrict__ __result = *__my_free_list;
403 __ret = _S_refill(_S_round_up(__n));
406 *__my_free_list = __result -> _M_free_list_link;
415 static void deallocate(void* __p, size_t __n)
417 if (__n > (size_t) _MAX_BYTES)
418 __mem_interface::deallocate(__p, __n);
421 _Obj* volatile* __my_free_list
422 = _S_free_list + _S_freelist_index(__n);
423 _Obj* __q = (_Obj*)__p;
428 _Lock __lock_instance;
429 # endif /* _NOTHREADS */
430 __q -> _M_free_list_link = *__my_free_list;
431 *__my_free_list = __q;
432 // lock is released here
436 static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz);
440 template <bool __threads, int __inst>
441 inline bool operator==(const __default_alloc_template<__threads, __inst>&,
442 const __default_alloc_template<__threads, __inst>&)
447 template <bool __threads, int __inst>
448 inline bool operator!=(const __default_alloc_template<__threads, __inst>&,
449 const __default_alloc_template<__threads, __inst>&)
455 // We allocate memory in large chunks in order to avoid fragmenting the
456 // malloc heap (or whatever __mem_interface is using) too much. We assume
457 // that __size is properly aligned. We hold the allocation lock.
458 template <bool __threads, int __inst>
460 __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size,
464 size_t __total_bytes = __size * __nobjs;
465 size_t __bytes_left = _S_end_free - _S_start_free;
467 if (__bytes_left >= __total_bytes)
469 __result = _S_start_free;
470 _S_start_free += __total_bytes;
473 else if (__bytes_left >= __size)
475 __nobjs = (int)(__bytes_left/__size);
476 __total_bytes = __size * __nobjs;
477 __result = _S_start_free;
478 _S_start_free += __total_bytes;
483 size_t __bytes_to_get =
484 2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
485 // Try to make use of the left-over piece.
486 if (__bytes_left > 0)
488 _Obj* volatile* __my_free_list =
489 _S_free_list + _S_freelist_index(__bytes_left);
491 ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
492 *__my_free_list = (_Obj*)_S_start_free;
494 _S_start_free = (char*) __mem_interface::allocate(__bytes_to_get);
495 if (0 == _S_start_free)
498 _Obj* volatile* __my_free_list;
500 // Try to make do with what we have. That can't hurt. We
501 // do not try smaller requests, since that tends to result
502 // in disaster on multi-process machines.
504 for (; __i <= (size_t) _MAX_BYTES; __i += (size_t) _ALIGN)
506 __my_free_list = _S_free_list + _S_freelist_index(__i);
507 __p = *__my_free_list;
510 *__my_free_list = __p -> _M_free_list_link;
511 _S_start_free = (char*)__p;
512 _S_end_free = _S_start_free + __i;
513 return(_S_chunk_alloc(__size, __nobjs));
514 // Any leftover piece will eventually make it to the
518 _S_end_free = 0; // In case of exception.
519 _S_start_free = (char*)__mem_interface::allocate(__bytes_to_get);
520 // This should either throw an
521 // exception or remedy the situation. Thus we assume it
524 _S_heap_size += __bytes_to_get;
525 _S_end_free = _S_start_free + __bytes_to_get;
526 return(_S_chunk_alloc(__size, __nobjs));
531 // Returns an object of size __n, and optionally adds to "size __n"'s free list.
532 // We assume that __n is properly aligned. We hold the allocation lock.
533 template <bool __threads, int __inst>
535 __default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
538 char* __chunk = _S_chunk_alloc(__n, __nobjs);
539 _Obj* volatile* __my_free_list;
545 if (1 == __nobjs) return(__chunk);
546 __my_free_list = _S_free_list + _S_freelist_index(__n);
548 /* Build free list in chunk */
549 __result = (_Obj*)__chunk;
550 *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
551 for (__i = 1; ; __i++) {
552 __current_obj = __next_obj;
553 __next_obj = (_Obj*)((char*)__next_obj + __n);
554 if (__nobjs - 1 == __i) {
555 __current_obj -> _M_free_list_link = 0;
558 __current_obj -> _M_free_list_link = __next_obj;
565 template <bool threads, int inst>
567 __default_alloc_template<threads, inst>::reallocate(void* __p,
574 if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) {
575 return(realloc(__p, __new_sz));
577 if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p);
578 __result = allocate(__new_sz);
579 __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
580 memcpy(__result, __p, __copy_sz);
581 deallocate(__p, __old_sz);
586 template <bool __threads, int __inst>
588 __default_alloc_template<__threads, __inst>::_S_node_allocator_lock
589 __STL_MUTEX_INITIALIZER;
593 template <bool __threads, int __inst>
594 char* __default_alloc_template<__threads, __inst>::_S_start_free = 0;
596 template <bool __threads, int __inst>
597 char* __default_alloc_template<__threads, __inst>::_S_end_free = 0;
599 template <bool __threads, int __inst>
600 size_t __default_alloc_template<__threads, __inst>::_S_heap_size = 0;
602 template <bool __threads, int __inst>
603 typename __default_alloc_template<__threads, __inst>::_Obj* volatile
604 __default_alloc_template<__threads, __inst> ::_S_free_list[
605 __default_alloc_template<__threads, __inst>::_NFREELISTS
606 ] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
609 // __NODE_ALLOCATOR_THREADS is predicated on __STL_THREADS being defined or not
610 typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
611 typedef __default_alloc_template<false, 0> single_client_alloc;
614 #endif /* ! __USE_MALLOC */
618 * This is a "standard" allocator, as per [20.4]. The private _Alloc is
619 * "SGI" style. (See comments at the top of stl_alloc.h.)
621 * The underlying allocator behaves as follows.
622 * - if __USE_MALLOC then
623 * - thread safety depends on malloc and is entirely out of our hands
624 * - __malloc_alloc_template is used for memory requests
625 * - else (the default)
626 * - __default_alloc_template is used via two typedefs
627 * - "single_client_alloc" typedef does no locking for threads
628 * - "alloc" typedef is threadsafe via the locks
629 * - __new_alloc is used for memory requests
635 typedef alloc _Alloc; // The underlying allocator.
637 typedef size_t size_type;
638 typedef ptrdiff_t difference_type;
639 typedef _Tp* pointer;
640 typedef const _Tp* const_pointer;
641 typedef _Tp& reference;
642 typedef const _Tp& const_reference;
643 typedef _Tp value_type;
645 template <class _Tp1> struct rebind {
646 typedef allocator<_Tp1> other;
649 allocator() throw() {}
650 allocator(const allocator&) throw() {}
651 template <class _Tp1> allocator(const allocator<_Tp1>&) throw() {}
652 ~allocator() throw() {}
654 pointer address(reference __x) const { return &__x; }
655 const_pointer address(const_reference __x) const { return &__x; }
657 // __n is permitted to be 0. The C++ standard says nothing about what
658 // the return value is when __n == 0.
659 _Tp* allocate(size_type __n, const void* = 0) {
660 return __n != 0 ? static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp)))
664 // __p is not permitted to be a null pointer.
665 void deallocate(pointer __p, size_type __n)
666 { _Alloc::deallocate(__p, __n * sizeof(_Tp)); }
668 size_type max_size() const throw()
669 { return size_t(-1) / sizeof(_Tp); }
671 void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
672 void destroy(pointer __p) { __p->~_Tp(); }
676 class allocator<void> {
678 typedef size_t size_type;
679 typedef ptrdiff_t difference_type;
680 typedef void* pointer;
681 typedef const void* const_pointer;
682 typedef void value_type;
684 template <class _Tp1> struct rebind {
685 typedef allocator<_Tp1> other;
690 template <class _T1, class _T2>
691 inline bool operator==(const allocator<_T1>&, const allocator<_T2>&)
696 template <class _T1, class _T2>
697 inline bool operator!=(const allocator<_T1>&, const allocator<_T2>&)
704 * Allocator adaptor to turn an "SGI" style allocator (e.g. alloc,
705 * __malloc_alloc_template) into a "standard" conformaing allocator. Note
706 * that this adaptor does *not* assume that all objects of the underlying
707 * alloc class are identical, nor does it assume that all of the underlying
708 * alloc's member functions are static member functions. Note, also, that
709 * __allocator<_Tp, alloc> is essentially the same thing as allocator<_Tp>.
711 template <class _Tp, class _Alloc>
714 _Alloc __underlying_alloc;
716 typedef size_t size_type;
717 typedef ptrdiff_t difference_type;
718 typedef _Tp* pointer;
719 typedef const _Tp* const_pointer;
720 typedef _Tp& reference;
721 typedef const _Tp& const_reference;
722 typedef _Tp value_type;
724 template <class _Tp1> struct rebind {
725 typedef __allocator<_Tp1, _Alloc> other;
728 __allocator() throw() {}
729 __allocator(const __allocator& __a) throw()
730 : __underlying_alloc(__a.__underlying_alloc) {}
731 template <class _Tp1>
732 __allocator(const __allocator<_Tp1, _Alloc>& __a) throw()
733 : __underlying_alloc(__a.__underlying_alloc) {}
734 ~__allocator() throw() {}
736 pointer address(reference __x) const { return &__x; }
737 const_pointer address(const_reference __x) const { return &__x; }
739 // __n is permitted to be 0.
740 _Tp* allocate(size_type __n, const void* = 0) {
742 ? static_cast<_Tp*>(__underlying_alloc.allocate(__n * sizeof(_Tp)))
746 // __p is not permitted to be a null pointer.
747 void deallocate(pointer __p, size_type __n)
748 { __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); }
750 size_type max_size() const throw()
751 { return size_t(-1) / sizeof(_Tp); }
753 void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
754 void destroy(pointer __p) { __p->~_Tp(); }
757 template <class _Alloc>
758 class __allocator<void, _Alloc> {
759 typedef size_t size_type;
760 typedef ptrdiff_t difference_type;
761 typedef void* pointer;
762 typedef const void* const_pointer;
763 typedef void value_type;
765 template <class _Tp1> struct rebind {
766 typedef __allocator<_Tp1, _Alloc> other;
770 template <class _Tp, class _Alloc>
771 inline bool operator==(const __allocator<_Tp, _Alloc>& __a1,
772 const __allocator<_Tp, _Alloc>& __a2)
774 return __a1.__underlying_alloc == __a2.__underlying_alloc;
777 template <class _Tp, class _Alloc>
778 inline bool operator!=(const __allocator<_Tp, _Alloc>& __a1,
779 const __allocator<_Tp, _Alloc>& __a2)
781 return __a1.__underlying_alloc != __a2.__underlying_alloc;
785 // Comparison operators for all of the predifined SGI-style allocators.
786 // This ensures that __allocator<malloc_alloc> (for example) will
790 inline bool operator==(const __malloc_alloc_template<inst>&,
791 const __malloc_alloc_template<inst>&)
796 template <int __inst>
797 inline bool operator!=(const __malloc_alloc_template<__inst>&,
798 const __malloc_alloc_template<__inst>&)
803 template <class _Alloc>
804 inline bool operator==(const __debug_alloc<_Alloc>&,
805 const __debug_alloc<_Alloc>&) {
809 template <class _Alloc>
810 inline bool operator!=(const __debug_alloc<_Alloc>&,
811 const __debug_alloc<_Alloc>&) {
816 // Another allocator adaptor: _Alloc_traits. This serves two
817 // purposes. First, make it possible to write containers that can use
818 // either SGI-style allocators or standard-conforming allocator.
819 // Second, provide a mechanism so that containers can query whether or
820 // not the allocator has distinct instances. If not, the container
821 // can avoid wasting a word of memory to store an empty object.
823 // This adaptor uses partial specialization. The general case of
824 // _Alloc_traits<_Tp, _Alloc> assumes that _Alloc is a
825 // standard-conforming allocator, possibly with non-equal instances
826 // and non-static members. (It still behaves correctly even if _Alloc
827 // has static member and if all instances are equal. Refinements
828 // affect performance, not correctness.)
830 // There are always two members: allocator_type, which is a standard-
831 // conforming allocator type for allocating objects of type _Tp, and
832 // _S_instanceless, a static const member of type bool. If
833 // _S_instanceless is true, this means that there is no difference
834 // between any two instances of type allocator_type. Furthermore, if
835 // _S_instanceless is true, then _Alloc_traits has one additional
836 // member: _Alloc_type. This type encapsulates allocation and
837 // deallocation of objects of type _Tp through a static interface; it
838 // has two member functions, whose signatures are
839 // static _Tp* allocate(size_t)
840 // static void deallocate(_Tp*, size_t)
842 // The fully general version.
844 template <class _Tp, class _Allocator>
847 static const bool _S_instanceless = false;
848 typedef typename _Allocator::template rebind<_Tp>::other allocator_type;
851 template <class _Tp, class _Allocator>
852 const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless;
854 // The version for the default allocator.
856 template <class _Tp, class _Tp1>
857 struct _Alloc_traits<_Tp, allocator<_Tp1> >
859 static const bool _S_instanceless = true;
860 typedef __simple_alloc<_Tp, alloc> _Alloc_type;
861 typedef allocator<_Tp> allocator_type;
864 // Versions for the predefined SGI-style allocators.
866 template <class _Tp, int __inst>
867 struct _Alloc_traits<_Tp, __malloc_alloc_template<__inst> >
869 static const bool _S_instanceless = true;
870 typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type;
871 typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
875 template <class _Tp, bool __threads, int __inst>
876 struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> >
878 static const bool _S_instanceless = true;
879 typedef __simple_alloc<_Tp, __default_alloc_template<__threads, __inst> >
881 typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> >
886 template <class _Tp, class _Alloc>
887 struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> >
889 static const bool _S_instanceless = true;
890 typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type;
891 typedef __allocator<_Tp, __debug_alloc<_Alloc> > allocator_type;
894 // Versions for the __allocator adaptor used with the predefined
895 // SGI-style allocators.
897 template <class _Tp, class _Tp1, int __inst>
898 struct _Alloc_traits<_Tp,
899 __allocator<_Tp1, __malloc_alloc_template<__inst> > >
901 static const bool _S_instanceless = true;
902 typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type;
903 typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
907 template <class _Tp, class _Tp1, bool __thr, int __inst>
908 struct _Alloc_traits<_Tp,
910 __default_alloc_template<__thr, __inst> > >
912 static const bool _S_instanceless = true;
913 typedef __simple_alloc<_Tp, __default_alloc_template<__thr,__inst> >
915 typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> >
920 template <class _Tp, class _Tp1, class _Alloc>
921 struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > >
923 static const bool _S_instanceless = true;
924 typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type;
925 typedef __allocator<_Tp, __debug_alloc<_Alloc> > allocator_type;
930 #endif /* __SGI_STL_INTERNAL_ALLOC_H */