2 * Copyright (c) 1996-1997
3 * Silicon Graphics Computer Systems, Inc.
5 * Permission to use, copy, modify, distribute and sell this software
6 * and its documentation for any purpose is hereby granted without fee,
7 * provided that the above copyright notice appear in all copies and
8 * that both that copyright notice and this permission notice appear
9 * in supporting documentation. Silicon Graphics makes no
10 * representations about the suitability of this software for any
11 * purpose. It is provided "as is" without express or implied warranty.
14 /* NOTE: This is an internal header file, included by other STL headers.
15 * You should not attempt to use it directly.
18 #ifndef __SGI_STL_INTERNAL_ALLOC_H
19 #define __SGI_STL_INTERNAL_ALLOC_H
22 # define __PRIVATE public
23 // Extra access restrictions prevent us from really making some things
26 # define __PRIVATE private
29 #ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
33 // This implements some standard node allocators. These are
34 // NOT the same as the allocators in the C++ draft standard or in
35 // in the original STL. They do not encapsulate different pointer
36 // types; indeed we assume that there is only one pointer type.
37 // The allocation primitives are intended to allocate individual objects,
38 // not larger arenas as with the original STL allocators.
42 # define __THROW_BAD_ALLOC throw bad_alloc()
43 #elif !defined(__THROW_BAD_ALLOC)
44 #if (defined(__BEOS__) || defined(__HAIKU__))
46 # define __THROW_BAD_ALLOC fprintf(stderr, "out of memory\n"); exit(1)
48 # include <iostream.h>
49 # define __THROW_BAD_ALLOC cerr << "out of memory" << endl; exit(1)
53 #ifdef __STL_WIN32THREADS
65 #if !defined(__STL_PTHREADS) && !defined(__STL_SOLTHREADS) \
66 && !defined(_NOTHREADS) \
67 && !defined(__STL_SGI_THREADS) && !defined(__STL_WIN32THREADS)
71 # ifdef __STL_PTHREADS
73 // This is dubious, since this is likely to be a high contention
74 // lock. Performance may not be adequate.
76 # define __NODE_ALLOCATOR_LOCK \
77 if (threads) pthread_mutex_lock(&_S_node_allocator_lock)
78 # define __NODE_ALLOCATOR_UNLOCK \
79 if (threads) pthread_mutex_unlock(&_S_node_allocator_lock)
80 # define __NODE_ALLOCATOR_THREADS true
81 # define __VOLATILE volatile // Needed at -O3 on SGI
83 # ifdef __STL_SOLTHREADS
85 # define __NODE_ALLOCATOR_LOCK \
86 if (threads) mutex_lock(&_S_node_allocator_lock)
87 # define __NODE_ALLOCATOR_UNLOCK \
88 if (threads) mutex_unlock(&_S_node_allocator_lock)
89 # define __NODE_ALLOCATOR_THREADS true
92 # ifdef __STL_WIN32THREADS
93 // The lock needs to be initialized by constructing an allocator
94 // objects of the right type. We do that here explicitly for alloc.
95 # define __NODE_ALLOCATOR_LOCK \
96 EnterCriticalSection(&_S_node_allocator_lock)
97 # define __NODE_ALLOCATOR_UNLOCK \
98 LeaveCriticalSection(&_S_node_allocator_lock)
99 # define __NODE_ALLOCATOR_THREADS true
100 # define __VOLATILE volatile // may not be needed
101 # endif /* WIN32THREADS */
102 # ifdef __STL_SGI_THREADS
103 // This should work without threads, with sproc threads, or with
104 // pthreads. It is suboptimal in all cases.
105 // It is unlikely to even compile on nonSGI machines.
108 extern int __us_rsthread_malloc
;
110 // The above is copied from malloc.h. Including <malloc.h>
111 // would be cleaner but fails with certain levels of standard
113 # define __NODE_ALLOCATOR_LOCK if (threads && __us_rsthread_malloc) \
114 { _S_lock(&_S_node_allocator_lock); }
115 # define __NODE_ALLOCATOR_UNLOCK if (threads && __us_rsthread_malloc) \
116 { _S_unlock(&_S_node_allocator_lock); }
117 # define __NODE_ALLOCATOR_THREADS true
118 # define __VOLATILE volatile // Needed at -O3 on SGI
122 # define __NODE_ALLOCATOR_LOCK
123 # define __NODE_ALLOCATOR_UNLOCK
124 # define __NODE_ALLOCATOR_THREADS false
128 __STL_BEGIN_NAMESPACE
130 #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
131 #pragma set woff 1174
134 // Malloc-based allocator. Typically slower than default alloc below.
135 // Typically thread-safe and more storage efficient.
136 #ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
137 # ifdef __DECLARE_GLOBALS_HERE
138 void (* __malloc_alloc_oom_handler
)() = 0;
139 // g++ 2.7.2 does not handle static template data members.
141 extern void (* __malloc_alloc_oom_handler
)();
145 template <int __inst
>
146 class __malloc_alloc_template
{
150 static void* _S_oom_malloc(size_t);
151 static void* _S_oom_realloc(void*, size_t);
153 #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
154 static void (* __malloc_alloc_oom_handler
)();
159 static void* allocate(size_t __n
)
161 void* __result
= malloc(__n
);
162 if (0 == __result
) __result
= _S_oom_malloc(__n
);
166 static void deallocate(void* __p
, size_t /* __n */)
171 static void* reallocate(void* __p
, size_t /* old_sz */, size_t __new_sz
)
173 void* __result
= realloc(__p
, __new_sz
);
174 if (0 == __result
) __result
= _S_oom_realloc(__p
, __new_sz
);
178 static void (* __set_malloc_handler(void (*__f
)()))()
180 void (* __old
)() = __malloc_alloc_oom_handler
;
181 __malloc_alloc_oom_handler
= __f
;
187 // malloc_alloc out-of-memory handling
189 #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
190 template <int __inst
>
191 void (* __malloc_alloc_template
<__inst
>::__malloc_alloc_oom_handler
)() = 0;
194 template <int __inst
>
196 __malloc_alloc_template
<__inst
>::_S_oom_malloc(size_t __n
)
198 void (* __my_malloc_handler
)();
202 __my_malloc_handler
= __malloc_alloc_oom_handler
;
203 if (0 == __my_malloc_handler
) { __THROW_BAD_ALLOC
; }
204 (*__my_malloc_handler
)();
205 __result
= malloc(__n
);
206 if (__result
) return(__result
);
210 template <int __inst
>
211 void* __malloc_alloc_template
<__inst
>::_S_oom_realloc(void* __p
, size_t __n
)
213 void (* __my_malloc_handler
)();
217 __my_malloc_handler
= __malloc_alloc_oom_handler
;
218 if (0 == __my_malloc_handler
) { __THROW_BAD_ALLOC
; }
219 (*__my_malloc_handler
)();
220 __result
= realloc(__p
, __n
);
221 if (__result
) return(__result
);
225 typedef __malloc_alloc_template
<0> malloc_alloc
;
227 template<class _Tp
, class _Alloc
>
231 static _Tp
* allocate(size_t __n
)
232 { return 0 == __n
? 0 : (_Tp
*) _Alloc::allocate(__n
* sizeof (_Tp
)); }
233 static _Tp
* allocate(void)
234 { return (_Tp
*) _Alloc::allocate(sizeof (_Tp
)); }
235 static void deallocate(_Tp
* __p
, size_t __n
)
236 { if (0 != __n
) _Alloc::deallocate(__p
, __n
* sizeof (_Tp
)); }
237 static void deallocate(_Tp
* __p
)
238 { _Alloc::deallocate(__p
, sizeof (_Tp
)); }
241 // Allocator adaptor to check size arguments for debugging.
242 // Reports errors using assert. Checking can be disabled with
243 // NDEBUG, but it's far better to just use the underlying allocator
244 // instead when no checking is desired.
245 // There is some evidence that this can confuse Purify.
246 template <class _Alloc
>
251 enum {_S_extra
= 8}; // Size of space used to store size. Note
252 // that this must be large enough to preserve
257 static void* allocate(size_t __n
)
259 char* __result
= (char*)_Alloc::allocate(__n
+ _S_extra
);
260 *(size_t*)__result
= __n
;
261 return __result
+ _S_extra
;
264 static void deallocate(void* __p
, size_t __n
)
266 char* __real_p
= (char*)__p
- _S_extra
;
267 assert(*(size_t*)__real_p
== __n
);
268 _Alloc::deallocate(__real_p
, __n
+ _S_extra
);
271 static void* reallocate(void* __p
, size_t __old_sz
, size_t __new_sz
)
273 char* __real_p
= (char*)__p
- _S_extra
;
274 assert(*(size_t*)__real_p
== __old_sz
);
275 char* __result
= (char*)
276 _Alloc::reallocate(__real_p
, __old_sz
+ _S_extra
, __new_sz
+ _S_extra
);
277 *(size_t*)__result
= __new_sz
;
278 return __result
+ _S_extra
;
286 typedef malloc_alloc alloc
;
287 typedef malloc_alloc single_client_alloc
;
292 // Default node allocator.
293 // With a reasonable compiler, this should be roughly as fast as the
294 // original STL class-specific allocators, but with less fragmentation.
295 // Default_alloc_template parameters are experimental and MAY
296 // DISAPPEAR in the future. Clients should just use alloc for now.
298 // Important implementation properties:
299 // 1. If the client request an object of size > _MAX_BYTES, the resulting
300 // object will be obtained directly from malloc.
301 // 2. In all other cases, we allocate an object of size exactly
302 // _S_round_up(requested_size). Thus the client has enough size
303 // information that we can return the object to the proper free list
304 // without permanently losing part of the object.
307 // The first template parameter specifies whether more than one thread
308 // may use this allocator. It is safe to allocate an object from
309 // one instance of a default_alloc and deallocate it with another
310 // one. This effectively transfers its ownership to the second one.
311 // This may have undesirable effects on reference locality.
312 // The second parameter is unreferenced and serves only to allow the
313 // creation of multiple default_alloc instances.
314 // Node that containers built on different allocator instances have
315 // different types, limiting the utility of this approach.
317 // breaks if we make these template class members:
319 enum {_MAX_BYTES
= 128};
320 enum {_NFREELISTS
= _MAX_BYTES
/_ALIGN
};
323 template <bool threads
, int inst
>
324 class __default_alloc_template
{
327 // Really we should use static const int x = N
328 // instead of enum { x = N }, but few compilers accept the former.
331 enum {_MAX_BYTES
= 128};
332 enum {_NFREELISTS
= _MAX_BYTES
/_ALIGN
};
335 _S_round_up(size_t __bytes
)
336 { return (((__bytes
) + _ALIGN
-1) & ~(_ALIGN
- 1)); }
340 union _Obj
* _M_free_list_link
;
341 char _M_client_data
[1]; /* The client sees this. */
345 static _Obj
* __VOLATILE _S_free_list
[];
346 // Specifying a size results in duplicate def for 4.1
348 static _Obj
* __VOLATILE _S_free_list
[_NFREELISTS
];
350 static size_t _S_freelist_index(size_t __bytes
) {
351 return (((__bytes
) + _ALIGN
-1)/_ALIGN
- 1);
354 // Returns an object of size __n, and optionally adds to size __n free list.
355 static void* _S_refill(size_t __n
);
356 // Allocates a chunk for nobjs of size "size". nobjs may be reduced
357 // if it is inconvenient to allocate the requested number.
358 static char* _S_chunk_alloc(size_t __size
, int& __nobjs
);
360 // Chunk allocation state.
361 static char* _S_start_free
;
362 static char* _S_end_free
;
363 static size_t _S_heap_size
;
365 # ifdef __STL_SGI_THREADS
366 static volatile unsigned long _S_node_allocator_lock
;
367 static void _S_lock(volatile unsigned long*);
368 static inline void _S_unlock(volatile unsigned long*);
371 # ifdef __STL_PTHREADS
372 static pthread_mutex_t _S_node_allocator_lock
;
375 # ifdef __STL_SOLTHREADS
376 static mutex_t _S_node_allocator_lock
;
379 # ifdef __STL_WIN32THREADS
380 static CRITICAL_SECTION _S_node_allocator_lock
;
381 static bool _S_node_allocator_lock_initialized
;
384 __default_alloc_template() {
385 // This assumes the first constructor is called before threads
387 if (!_S_node_allocator_lock_initialized
) {
388 InitializeCriticalSection(&_S_node_allocator_lock
);
389 _S_node_allocator_lock_initialized
= true;
397 _Lock() { __NODE_ALLOCATOR_LOCK
; }
398 ~_Lock() { __NODE_ALLOCATOR_UNLOCK
; }
404 /* __n must be > 0 */
405 static void* allocate(size_t __n
)
407 _Obj
* __VOLATILE
* __my_free_list
;
408 _Obj
* __RESTRICT __result
;
410 if (__n
> (size_t) _MAX_BYTES
) {
411 return(malloc_alloc::allocate(__n
));
413 __my_free_list
= _S_free_list
+ _S_freelist_index(__n
);
414 // Acquire the lock here with a constructor call.
415 // This ensures that it is released in exit or during stack
419 _Lock __lock_instance
;
421 __result
= *__my_free_list
;
423 void* __r
= _S_refill(_S_round_up(__n
));
426 *__my_free_list
= __result
-> _M_free_list_link
;
430 /* __p may not be 0 */
431 static void deallocate(void* __p
, size_t __n
)
433 _Obj
* __q
= (_Obj
*)__p
;
434 _Obj
* __VOLATILE
* __my_free_list
;
436 if (__n
> (size_t) _MAX_BYTES
) {
437 malloc_alloc::deallocate(__p
, __n
);
440 __my_free_list
= _S_free_list
+ _S_freelist_index(__n
);
444 _Lock __lock_instance
;
445 # endif /* _NOTHREADS */
446 __q
-> _M_free_list_link
= *__my_free_list
;
447 *__my_free_list
= __q
;
448 // lock is released here
451 static void* reallocate(void* __p
, size_t __old_sz
, size_t __new_sz
);
455 typedef __default_alloc_template
<__NODE_ALLOCATOR_THREADS
, 0> alloc
;
456 typedef __default_alloc_template
<false, 0> single_client_alloc
;
460 /* We allocate memory in large chunks in order to avoid fragmenting */
461 /* the malloc heap too much. */
462 /* We assume that size is properly aligned. */
463 /* We hold the allocation lock. */
464 template <bool __threads
, int __inst
>
466 __default_alloc_template
<__threads
, __inst
>::_S_chunk_alloc(size_t __size
,
470 size_t __total_bytes
= __size
* __nobjs
;
471 size_t __bytes_left
= _S_end_free
- _S_start_free
;
473 if (__bytes_left
>= __total_bytes
) {
474 __result
= _S_start_free
;
475 _S_start_free
+= __total_bytes
;
477 } else if (__bytes_left
>= __size
) {
478 __nobjs
= (int)(__bytes_left
/__size
);
479 __total_bytes
= __size
* __nobjs
;
480 __result
= _S_start_free
;
481 _S_start_free
+= __total_bytes
;
484 size_t __bytes_to_get
=
485 2 * __total_bytes
+ _S_round_up(_S_heap_size
>> 4);
486 // Try to make use of the left-over piece.
487 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*)malloc(__bytes_to_get
);
495 if (0 == _S_start_free
) {
497 _Obj
* __VOLATILE
* __my_free_list
;
499 // Try to make do with what we have. That can't
500 // hurt. We do not try smaller requests, since that tends
501 // to result in disaster on multi-process machines.
502 for (__i
= __size
; __i
<= _MAX_BYTES
; __i
+= _ALIGN
) {
503 __my_free_list
= _S_free_list
+ _S_freelist_index(__i
);
504 __p
= *__my_free_list
;
506 *__my_free_list
= __p
-> _M_free_list_link
;
507 _S_start_free
= (char*)__p
;
508 _S_end_free
= _S_start_free
+ __i
;
509 return(_S_chunk_alloc(__size
, __nobjs
));
510 // Any leftover piece will eventually make it to the
514 _S_end_free
= 0; // In case of exception.
515 _S_start_free
= (char*)malloc_alloc::allocate(__bytes_to_get
);
516 // This should either throw an
517 // exception or remedy the situation. Thus we assume it
520 _S_heap_size
+= __bytes_to_get
;
521 _S_end_free
= _S_start_free
+ __bytes_to_get
;
522 return(_S_chunk_alloc(__size
, __nobjs
));
527 /* Returns an object of size __n, and optionally adds to size __n free list.*/
528 /* We assume that __n is properly aligned. */
529 /* We hold the allocation lock. */
530 template <bool __threads
, int __inst
>
532 __default_alloc_template
<__threads
, __inst
>::_S_refill(size_t __n
)
535 char* __chunk
= _S_chunk_alloc(__n
, __nobjs
);
536 _Obj
* __VOLATILE
* __my_free_list
;
542 if (1 == __nobjs
) return(__chunk
);
543 __my_free_list
= _S_free_list
+ _S_freelist_index(__n
);
545 /* Build free list in chunk */
546 __result
= (_Obj
*)__chunk
;
547 *__my_free_list
= __next_obj
= (_Obj
*)(__chunk
+ __n
);
548 for (__i
= 1; ; __i
++) {
549 __current_obj
= __next_obj
;
550 __next_obj
= (_Obj
*)((char*)__next_obj
+ __n
);
551 if (__nobjs
- 1 == __i
) {
552 __current_obj
-> _M_free_list_link
= 0;
555 __current_obj
-> _M_free_list_link
= __next_obj
;
561 template <bool threads
, int inst
>
563 __default_alloc_template
<threads
, inst
>::reallocate(void* __p
,
570 if (__old_sz
> (size_t) _MAX_BYTES
&& __new_sz
> (size_t) _MAX_BYTES
) {
571 return(realloc(__p
, __new_sz
));
573 if (_S_round_up(__old_sz
) == _S_round_up(__new_sz
)) return(__p
);
574 __result
= allocate(__new_sz
);
575 __copy_sz
= __new_sz
> __old_sz
? __old_sz
: __new_sz
;
576 memcpy(__result
, __p
, __copy_sz
);
577 deallocate(__p
, __old_sz
);
581 #ifdef __STL_PTHREADS
582 template <bool __threads
, int __inst
>
584 __default_alloc_template
<__threads
, __inst
>::_S_node_allocator_lock
585 = PTHREAD_MUTEX_INITIALIZER
;
588 #ifdef __STL_SOLTHREADS
589 template <bool __threads
, int __inst
>
591 __default_alloc_template
<__threads
, __inst
>::_S_node_allocator_lock
595 #ifdef __STL_WIN32THREADS
596 template <bool __threads
, int __inst
>
598 __default_alloc_template
<__threads
, __inst
>::
599 _S_node_allocator_lock
;
601 template <bool __threads
, int __inst
>
603 __default_alloc_template
<__threads
, __inst
>::
604 _S_node_allocator_lock_initialized
608 #ifdef __STL_SGI_THREADS
611 #include <time.h> /* XXX should use <ctime> */
612 __STL_BEGIN_NAMESPACE
613 // Somewhat generic lock implementations. We need only test-and-set
614 // and some way to sleep. These should work with both SGI pthreads
615 // and sproc threads. They may be useful on other systems.
616 template <bool __threads
, int __inst
>
617 volatile unsigned long
618 __default_alloc_template
<__threads
, __inst
>::_S_node_allocator_lock
= 0;
620 #if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) || defined(__GNUC__)
621 # define __test_and_set(l,v) test_and_set(l,v)
624 template <bool __threads
, int __inst
>
626 __default_alloc_template
<__threads
, __inst
>::
627 _S_lock(volatile unsigned long* __lock
)
629 const unsigned __low_spin_max
= 30; // spins if we suspect uniprocessor
630 const unsigned __high_spin_max
= 1000; // spins for multiprocessor
631 static unsigned __spin_max
= __low_spin_max
;
632 unsigned __my_spin_max
;
633 static unsigned __last_spins
= 0;
634 unsigned __my_last_spins
;
636 # define __ALLOC_PAUSE \
637 __junk *= __junk; __junk *= __junk; __junk *= __junk; __junk *= __junk
640 if (!__test_and_set((unsigned long*)__lock
, 1)) {
643 __my_spin_max
= __spin_max
;
644 __my_last_spins
= __last_spins
;
645 for (__i
= 0; __i
< __my_spin_max
; __i
++) {
646 if (__i
< __my_last_spins
/2 || *__lock
) {
650 if (!__test_and_set((unsigned long*)__lock
, 1)) {
652 // Spinning worked. Thus we're probably not being scheduled
653 // against the other process with which we were contending.
654 // Thus it makes sense to spin longer the next time.
656 __spin_max
= __high_spin_max
;
660 // We are probably being scheduled against the other process. Sleep.
661 __spin_max
= __low_spin_max
;
662 for (__i
= 0 ;; ++__i
) {
663 struct timespec __ts
;
664 int __log_nsec
= __i
+ 6;
666 if (!__test_and_set((unsigned long *)__lock
, 1)) {
669 if (__log_nsec
> 27) __log_nsec
= 27;
670 /* Max sleep is 2**27nsec ~ 60msec */
672 __ts
.tv_nsec
= 1 << __log_nsec
;
677 template <bool __threads
, int __inst
>
679 __default_alloc_template
<__threads
, __inst
>::_S_unlock(
680 volatile unsigned long* __lock
)
682 # if defined(__GNUC__) && __mips >= 3
685 # elif __mips >= 3 && (defined (_ABIN32) || defined(_ABI64))
686 __lock_release(__lock
);
689 // This is not sufficient on many multiprocessors, since
690 // writes to protected variables and the lock may be reordered.
695 template <bool __threads
, int __inst
>
696 char* __default_alloc_template
<__threads
, __inst
>::_S_start_free
= 0;
698 template <bool __threads
, int __inst
>
699 char* __default_alloc_template
<__threads
, __inst
>::_S_end_free
= 0;
701 template <bool __threads
, int __inst
>
702 size_t __default_alloc_template
<__threads
, __inst
>::_S_heap_size
= 0;
704 template <bool __threads
, int __inst
>
705 __default_alloc_template
<__threads
, __inst
>::_Obj
* __VOLATILE
706 __default_alloc_template
<__threads
, __inst
> ::_S_free_list
[
708 ] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
709 // The 16 zeros are necessary to make version 4.1 of the SunPro
710 // compiler happy. Otherwise it appears to allocate too little
711 // space for the array.
713 # ifdef __STL_WIN32THREADS
714 // Create one to get critical section initialized.
715 // We do this onece per file, but only the first constructor
717 static alloc __node_allocator_dummy_instance
;
720 #endif /* ! __USE_MALLOC */
722 // This implements allocators as specified in the C++ standard.
724 // Note that standard-conforming allocators use many language features
725 // that are not yet widely implemented. In particular, they rely on
726 // member templates, partial specialization, partial ordering of function
727 // templates, the typename keyword, and the use of the template keyword
728 // to refer to a template member of a dependent type.
730 #ifdef __STL_USE_STD_ALLOCATORS
734 typedef alloc _Alloc
; // The underlying allocator.
736 typedef size_t size_type
;
737 typedef ptrdiff_t difference_type
;
738 typedef _Tp
* pointer
;
739 typedef const _Tp
* const_pointer
;
740 typedef _Tp
& reference
;
741 typedef const _Tp
& const_reference
;
742 typedef _Tp value_type
;
744 template <class _Tp1
> struct rebind
{
745 typedef allocator
<_Tp1
> other
;
748 allocator() __STL_NOTHROW
{}
749 allocator(const allocator
&) __STL_NOTHROW
{}
750 template <class _Tp1
> allocator(const allocator
<_Tp1
>&) __STL_NOTHROW
{}
751 ~allocator() __STL_NOTHROW
{}
753 pointer
address(reference __x
) const { return &__x
; }
754 const_pointer
address(const_reference __x
) const { return &__x
; }
756 // __n is permitted to be 0. The C++ standard says nothing about what
757 // the return value is when __n == 0.
758 _Tp
* allocate(size_type __n
, const void* = 0) {
759 return __n
!= 0 ? static_cast<_Tp
*>(_Alloc::allocate(__n
* sizeof(_Tp
)))
763 // __p is not permitted to be a null pointer.
764 void deallocate(pointer __p
, size_type __n
)
765 { _Alloc::deallocate(__p
, __n
* sizeof(_Tp
)); }
767 size_type
max_size() const __STL_NOTHROW
768 { return size_t(-1) / sizeof(_Tp
); }
770 void construct(pointer __p
, const _Tp
& __val
) { new(__p
) _Tp(__val
); }
771 void destroy(pointer __p
) { __p
->~_Tp(); }
775 class allocator
<void> {
776 typedef size_t size_type
;
777 typedef ptrdiff_t difference_type
;
778 typedef void* pointer
;
779 typedef const void* const_pointer
;
780 typedef void value_type
;
782 template <class _Tp1
> struct rebind
{
783 typedef allocator
<_Tp1
> other
;
788 template <class _T1
, class _T2
>
789 inline bool operator==(const allocator
<_T1
>&, const allocator
<_T2
>&)
794 template <class _T1
, class _T2
>
795 inline bool operator!=(const allocator
<_T1
>&, const allocator
<_T2
>&)
800 // Allocator adaptor to turn an SGI-style allocator (e.g. alloc, malloc_alloc)
801 // into a standard-conforming allocator. Note that this adaptor does
802 // *not* assume that all objects of the underlying alloc class are
803 // identical, nor does it assume that all of the underlying alloc's
804 // member functions are static member functions. Note, also, that
805 // __allocator<_Tp, alloc> is essentially the same thing as allocator<_Tp>.
807 template <class _Tp
, class _Alloc
>
809 _Alloc __underlying_alloc
;
811 typedef size_t size_type
;
812 typedef ptrdiff_t difference_type
;
813 typedef _Tp
* pointer
;
814 typedef const _Tp
* const_pointer
;
815 typedef _Tp
& reference
;
816 typedef const _Tp
& const_reference
;
817 typedef _Tp value_type
;
819 template <class _Tp1
> struct rebind
{
820 typedef __allocator
<_Tp1
, _Alloc
> other
;
823 __allocator() __STL_NOTHROW
{}
824 __allocator(const __allocator
& __a
) __STL_NOTHROW
825 : __underlying_alloc(__a
.__underlying_alloc
) {}
826 template <class _Tp1
>
827 __allocator(const __allocator
<_Tp1
, _Alloc
>& __a
) __STL_NOTHROW
828 : __underlying_alloc(__a
.__underlying_alloc
) {}
829 ~__allocator() __STL_NOTHROW
{}
831 pointer
address(reference __x
) const { return &__x
; }
832 const_pointer
address(const_reference __x
) const { return &__x
; }
834 // __n is permitted to be 0.
835 _Tp
* allocate(size_type __n
, const void* = 0) {
837 ? static_cast<_Tp
*>(__underlying_alloc
.allocate(__n
* sizeof(_Tp
)))
841 // __p is not permitted to be a null pointer.
842 void deallocate(pointer __p
, size_type __n
)
843 { __underlying_alloc
.deallocate(__p
, __n
* sizeof(_Tp
)); }
845 size_type
max_size() const __STL_NOTHROW
846 { return size_t(-1) / sizeof(_Tp
); }
848 void construct(pointer __p
, const _Tp
& __val
) { new(__p
) _Tp(__val
); }
849 void destroy(pointer __p
) { __p
->~_Tp(); }
852 template <class _Alloc
>
853 class __allocator
<void, _Alloc
> {
854 typedef size_t size_type
;
855 typedef ptrdiff_t difference_type
;
856 typedef void* pointer
;
857 typedef const void* const_pointer
;
858 typedef void value_type
;
860 template <class _Tp1
> struct rebind
{
861 typedef __allocator
<_Tp1
, _Alloc
> other
;
865 template <class _Tp
, class _Alloc
>
866 inline bool operator==(const __allocator
<_Tp
, _Alloc
>& __a1
,
867 const __allocator
<_Tp
, _Alloc
>& __a2
)
869 return __a1
.__underlying_alloc
== __a2
.__underlying_alloc
;
872 #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
873 template <class _Tp
, class _Alloc
>
874 inline bool operator!=(const __allocator
<_Tp
, _Alloc
>& __a1
,
875 const __allocator
<_Tp
, _Alloc
>& __a2
)
877 return __a1
.__underlying_alloc
!= __a2
.__underlying_alloc
;
879 #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
881 // Comparison operators for all of the predifined SGI-style allocators.
882 // This ensures that __allocator<malloc_alloc> (for example) will
886 inline bool operator==(const __malloc_alloc_template
<inst
>&,
887 const __malloc_alloc_template
<inst
>&)
892 #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
893 template <int __inst
>
894 inline bool operator!=(const __malloc_alloc_template
<__inst
>&,
895 const __malloc_alloc_template
<__inst
>&)
899 #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
902 template <bool __threads
, int __inst
>
903 inline bool operator==(const __default_alloc_template
<__threads
, __inst
>&,
904 const __default_alloc_template
<__threads
, __inst
>&)
909 # ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
910 template <bool __threads
, int __inst
>
911 inline bool operator!=(const __default_alloc_template
<__threads
, __inst
>&,
912 const __default_alloc_template
<__threads
, __inst
>&)
916 # endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
919 template <class _Alloc
>
920 inline bool operator==(const debug_alloc
<_Alloc
>&,
921 const debug_alloc
<_Alloc
>&) {
925 #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
926 template <class _Alloc
>
927 inline bool operator!=(const debug_alloc
<_Alloc
>&,
928 const debug_alloc
<_Alloc
>&) {
931 #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
933 // Another allocator adaptor: _Alloc_traits. This serves two
934 // purposes. First, make it possible to write containers that can use
935 // either SGI-style allocators or standard-conforming allocator.
936 // Second, provide a mechanism so that containers can query whether or
937 // not the allocator has distinct instances. If not, the container
938 // can avoid wasting a word of memory to store an empty object.
940 // This adaptor uses partial specialization. The general case of
941 // _Alloc_traits<_Tp, _Alloc> assumes that _Alloc is a
942 // standard-conforming allocator, possibly with non-equal instances
943 // and non-static members. (It still behaves correctly even if _Alloc
944 // has static member and if all instances are equal. Refinements
945 // affect performance, not correctness.)
947 // There are always two members: allocator_type, which is a standard-
948 // conforming allocator type for allocating objects of type _Tp, and
949 // _S_instanceless, a static const member of type bool. If
950 // _S_instanceless is true, this means that there is no difference
951 // between any two instances of type allocator_type. Furthermore, if
952 // _S_instanceless is true, then _Alloc_traits has one additional
953 // member: _Alloc_type. This type encapsulates allocation and
954 // deallocation of objects of type _Tp through a static interface; it
955 // has two member functions, whose signatures are
956 // static _Tp* allocate(size_t)
957 // static void deallocate(_Tp*, size_t)
959 // The fully general version.
961 template <class _Tp
, class _Allocator
>
964 static const bool _S_instanceless
= false;
965 typedef typename
_Allocator::__STL_TEMPLATE rebind
<_Tp
>::other
969 template <class _Tp
, class _Allocator
>
970 const bool _Alloc_traits
<_Tp
, _Allocator
>::_S_instanceless
;
972 // The version for the default allocator.
974 template <class _Tp
, class _Tp1
>
975 struct _Alloc_traits
<_Tp
, allocator
<_Tp1
> >
977 static const bool _S_instanceless
= true;
978 typedef simple_alloc
<_Tp
, alloc
> _Alloc_type
;
979 typedef allocator
<_Tp
> allocator_type
;
982 // Versions for the predefined SGI-style allocators.
984 template <class _Tp
, int __inst
>
985 struct _Alloc_traits
<_Tp
, __malloc_alloc_template
<__inst
> >
987 static const bool _S_instanceless
= true;
988 typedef simple_alloc
<_Tp
, __malloc_alloc_template
<__inst
> > _Alloc_type
;
989 typedef __allocator
<_Tp
, __malloc_alloc_template
<__inst
> > allocator_type
;
993 template <class _Tp
, bool __threads
, int __inst
>
994 struct _Alloc_traits
<_Tp
, __default_alloc_template
<__threads
, __inst
> >
996 static const bool _S_instanceless
= true;
997 typedef simple_alloc
<_Tp
, __default_alloc_template
<__threads
, __inst
> >
999 typedef __allocator
<_Tp
, __default_alloc_template
<__threads
, __inst
> >
1004 template <class _Tp
, class _Alloc
>
1005 struct _Alloc_traits
<_Tp
, debug_alloc
<_Alloc
> >
1007 static const bool _S_instanceless
= true;
1008 typedef simple_alloc
<_Tp
, debug_alloc
<_Alloc
> > _Alloc_type
;
1009 typedef __allocator
<_Tp
, debug_alloc
<_Alloc
> > allocator_type
;
1012 // Versions for the __allocator adaptor used with the predefined
1013 // SGI-style allocators.
1015 template <class _Tp
, class _Tp1
, int __inst
>
1016 struct _Alloc_traits
<_Tp
,
1017 __allocator
<_Tp1
, __malloc_alloc_template
<__inst
> > >
1019 static const bool _S_instanceless
= true;
1020 typedef simple_alloc
<_Tp
, __malloc_alloc_template
<__inst
> > _Alloc_type
;
1021 typedef __allocator
<_Tp
, __malloc_alloc_template
<__inst
> > allocator_type
;
1024 #ifndef __USE_MALLOC
1025 template <class _Tp
, class _Tp1
, bool __thr
, int __inst
>
1026 struct _Alloc_traits
<_Tp
,
1028 __default_alloc_template
<__thr
, __inst
> > >
1030 static const bool _S_instanceless
= true;
1031 typedef simple_alloc
<_Tp
, __default_alloc_template
<__thr
,__inst
> >
1033 typedef __allocator
<_Tp
, __default_alloc_template
<__thr
,__inst
> >
1038 template <class _Tp
, class _Tp1
, class _Alloc
>
1039 struct _Alloc_traits
<_Tp
, __allocator
<_Tp1
, debug_alloc
<_Alloc
> > >
1041 static const bool _S_instanceless
= true;
1042 typedef simple_alloc
<_Tp
, debug_alloc
<_Alloc
> > _Alloc_type
;
1043 typedef __allocator
<_Tp
, debug_alloc
<_Alloc
> > allocator_type
;
1047 #endif /* __STL_USE_STD_ALLOCATORS */
1049 #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
1050 #pragma reset woff 1174
1057 #endif /* __SGI_STL_INTERNAL_ALLOC_H */