stl_allo.h
上传用户:nizebo
上传日期:2022-05-14
资源大小:882k
文件大小:28k
源码类别:

STL

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 1996-1997
  3.  * Silicon Graphics Computer Systems, Inc.
  4.  *
  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.
  12.  */
  13. /* NOTE: This is an internal header file, included by other STL headers.
  14.  *   You should not attempt to use it directly.
  15.  */
  16. #ifndef __SGI_STL_INTERNAL_ALLOC_H
  17. #define __SGI_STL_INTERNAL_ALLOC_H
  18. #ifdef __SUNPRO_CC
  19. #  define __PRIVATE public
  20.    // Extra access restrictions prevent us from really making some things
  21.    // private.
  22. #else
  23. #  define __PRIVATE private
  24. #endif
  25. #ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
  26. #  define __USE_MALLOC
  27. #endif
  28. // This implements some standard node allocators.  These are
  29. // NOT the same as the allocators in the C++ draft standard or in
  30. // in the original STL.  They do not encapsulate different pointer
  31. // types; indeed we assume that there is only one pointer type.
  32. // The allocation primitives are intended to allocate individual objects,
  33. // not larger arenas as with the original STL allocators.
  34. #ifndef __THROW_BAD_ALLOC
  35. #  if defined(__STL_NO_BAD_ALLOC) || !defined(__STL_USE_EXCEPTIONS)
  36. #    include <stdio.h>
  37. #    include <stdlib.h>
  38. #    define __THROW_BAD_ALLOC fprintf(stderr, "out of memoryn"); exit(1)
  39. #  else /* Standard conforming out-of-memory handling */
  40. #    include <new>
  41. #    define __THROW_BAD_ALLOC throw std::bad_alloc()
  42. #  endif
  43. #endif
  44. #include <stddef.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <assert.h>
  48. #ifndef __RESTRICT
  49. #  define __RESTRICT
  50. #endif
  51. #ifdef __STL_THREADS
  52. # include <stl_threads.h>
  53. # define __NODE_ALLOCATOR_THREADS true
  54. # ifdef __STL_SGI_THREADS
  55.   // We test whether threads are in use before locking.
  56.   // Perhaps this should be moved into stl_threads.h, but that
  57.   // probably makes it harder to avoid the procedure call when
  58.   // it isn't needed.
  59.     extern "C" {
  60.       extern int __us_rsthread_malloc;
  61.     }
  62. // The above is copied from malloc.h.  Including <malloc.h>
  63. // would be cleaner but fails with certain levels of standard
  64. // conformance.
  65. #   define __NODE_ALLOCATOR_LOCK if (threads && __us_rsthread_malloc) 
  66.                 { _S_node_allocator_lock._M_acquire_lock(); }
  67. #   define __NODE_ALLOCATOR_UNLOCK if (threads && __us_rsthread_malloc) 
  68.                 { _S_node_allocator_lock._M_release_lock(); }
  69. # else /* !__STL_SGI_THREADS */
  70. #   define __NODE_ALLOCATOR_LOCK 
  71.         { if (threads) _S_node_allocator_lock._M_acquire_lock(); }
  72. #   define __NODE_ALLOCATOR_UNLOCK 
  73.         { if (threads) _S_node_allocator_lock._M_release_lock(); }
  74. # endif
  75. #else
  76. //  Thread-unsafe
  77. #   define __NODE_ALLOCATOR_LOCK
  78. #   define __NODE_ALLOCATOR_UNLOCK
  79. #   define __NODE_ALLOCATOR_THREADS false
  80. #endif
  81. __STL_BEGIN_NAMESPACE
  82. #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
  83. #pragma set woff 1174
  84. #endif
  85. // Malloc-based allocator.  Typically slower than default alloc below.
  86. // Typically thread-safe and more storage efficient.
  87. #ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
  88. # ifdef __DECLARE_GLOBALS_HERE
  89.     void (* __malloc_alloc_oom_handler)() = 0;
  90.     // g++ 2.7.2 does not handle static template data members.
  91. # else
  92.     extern void (* __malloc_alloc_oom_handler)();
  93. # endif
  94. #endif
  95. template <int __inst>
  96. class __malloc_alloc_template {
  97. private:
  98.   static void* _S_oom_malloc(size_t);
  99.   static void* _S_oom_realloc(void*, size_t);
  100. #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
  101.   static void (* __malloc_alloc_oom_handler)();
  102. #endif
  103. public:
  104.   static void* allocate(size_t __n)
  105.   {
  106.     void* __result = malloc(__n);
  107.     if (0 == __result) __result = _S_oom_malloc(__n);
  108.     return __result;
  109.   }
  110.   static void deallocate(void* __p, size_t /* __n */)
  111.   {
  112.     free(__p);
  113.   }
  114.   static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz)
  115.   {
  116.     void* __result = realloc(__p, __new_sz);
  117.     if (0 == __result) __result = _S_oom_realloc(__p, __new_sz);
  118.     return __result;
  119.   }
  120.   static void (* __set_malloc_handler(void (*__f)()))()
  121.   {
  122.     void (* __old)() = __malloc_alloc_oom_handler;
  123.     __malloc_alloc_oom_handler = __f;
  124.     return(__old);
  125.   }
  126. };
  127. // malloc_alloc out-of-memory handling
  128. #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
  129. template <int __inst>
  130. void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0;
  131. #endif
  132. template <int __inst>
  133. void*
  134. __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
  135. {
  136.     void (* __my_malloc_handler)();
  137.     void* __result;
  138.     for (;;) {
  139.         __my_malloc_handler = __malloc_alloc_oom_handler;
  140.         if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; }
  141.         (*__my_malloc_handler)();
  142.         __result = malloc(__n);
  143.         if (__result) return(__result);
  144.     }
  145. }
  146. template <int __inst>
  147. void* __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n)
  148. {
  149.     void (* __my_malloc_handler)();
  150.     void* __result;
  151.     for (;;) {
  152.         __my_malloc_handler = __malloc_alloc_oom_handler;
  153.         if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; }
  154.         (*__my_malloc_handler)();
  155.         __result = realloc(__p, __n);
  156.         if (__result) return(__result);
  157.     }
  158. }
  159. typedef __malloc_alloc_template<0> malloc_alloc;
  160. template<class _Tp, class _Alloc>
  161. class simple_alloc {
  162. public:
  163.     static _Tp* allocate(size_t __n)
  164.       { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
  165.     static _Tp* allocate(void)
  166.       { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }
  167.     static void deallocate(_Tp* __p, size_t __n)
  168.       { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }
  169.     static void deallocate(_Tp* __p)
  170.       { _Alloc::deallocate(__p, sizeof (_Tp)); }
  171. };
  172. // Allocator adaptor to check size arguments for debugging.
  173. // Reports errors using assert.  Checking can be disabled with
  174. // NDEBUG, but it's far better to just use the underlying allocator
  175. // instead when no checking is desired.
  176. // There is some evidence that this can confuse Purify.
  177. template <class _Alloc>
  178. class debug_alloc {
  179. private:
  180.   enum {_S_extra = 8};  // Size of space used to store size.  Note
  181.                         // that this must be large enough to preserve
  182.                         // alignment.
  183. public:
  184.   static void* allocate(size_t __n)
  185.   {
  186.     char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra);
  187.     *(size_t*)__result = __n;
  188.     return __result + (int) _S_extra;
  189.   }
  190.   static void deallocate(void* __p, size_t __n)
  191.   {
  192.     char* __real_p = (char*)__p - (int) _S_extra;
  193.     assert(*(size_t*)__real_p == __n);
  194.     _Alloc::deallocate(__real_p, __n + (int) _S_extra);
  195.   }
  196.   static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz)
  197.   {
  198.     char* __real_p = (char*)__p - (int) _S_extra;
  199.     assert(*(size_t*)__real_p == __old_sz);
  200.     char* __result = (char*)
  201.       _Alloc::reallocate(__real_p, __old_sz + (int) _S_extra,
  202.                                    __new_sz + (int) _S_extra);
  203.     *(size_t*)__result = __new_sz;
  204.     return __result + (int) _S_extra;
  205.   }
  206. };
  207. # ifdef __USE_MALLOC
  208. typedef malloc_alloc alloc;
  209. typedef malloc_alloc single_client_alloc;
  210. # else
  211. // Default node allocator.
  212. // With a reasonable compiler, this should be roughly as fast as the
  213. // original STL class-specific allocators, but with less fragmentation.
  214. // Default_alloc_template parameters are experimental and MAY
  215. // DISAPPEAR in the future.  Clients should just use alloc for now.
  216. //
  217. // Important implementation properties:
  218. // 1. If the client request an object of size > _MAX_BYTES, the resulting
  219. //    object will be obtained directly from malloc.
  220. // 2. In all other cases, we allocate an object of size exactly
  221. //    _S_round_up(requested_size).  Thus the client has enough size
  222. //    information that we can return the object to the proper free list
  223. //    without permanently losing part of the object.
  224. //
  225. // The first template parameter specifies whether more than one thread
  226. // may use this allocator.  It is safe to allocate an object from
  227. // one instance of a default_alloc and deallocate it with another
  228. // one.  This effectively transfers its ownership to the second one.
  229. // This may have undesirable effects on reference locality.
  230. // The second parameter is unreferenced and serves only to allow the
  231. // creation of multiple default_alloc instances.
  232. // Node that containers built on different allocator instances have
  233. // different types, limiting the utility of this approach.
  234. #if defined(__SUNPRO_CC) || defined(__GNUC__)
  235. // breaks if we make these template class members:
  236.   enum {_ALIGN = 8};
  237.   enum {_MAX_BYTES = 128};
  238.   enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN
  239. #endif
  240. template <bool threads, int inst>
  241. class __default_alloc_template {
  242. private:
  243.   // Really we should use static const int x = N
  244.   // instead of enum { x = N }, but few compilers accept the former.
  245. #if ! (defined(__SUNPRO_CC) || defined(__GNUC__))
  246.     enum {_ALIGN = 8};
  247.     enum {_MAX_BYTES = 128};
  248.     enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN
  249. # endif
  250.   static size_t
  251.   _S_round_up(size_t __bytes) 
  252.     { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); }
  253. __PRIVATE:
  254.   union _Obj {
  255.         union _Obj* _M_free_list_link;
  256.         char _M_client_data[1];    /* The client sees this.        */
  257.   };
  258. private:
  259. # if defined(__SUNPRO_CC) || defined(__GNUC__) || defined(__HP_aCC)
  260.     static _Obj* __STL_VOLATILE _S_free_list[]; 
  261.         // Specifying a size results in duplicate def for 4.1
  262. # else
  263.     static _Obj* __STL_VOLATILE _S_free_list[_NFREELISTS]; 
  264. # endif
  265.   static  size_t _S_freelist_index(size_t __bytes) {
  266.         return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1);
  267.   }
  268.   // Returns an object of size __n, and optionally adds to size __n free list.
  269.   static void* _S_refill(size_t __n);
  270.   // Allocates a chunk for nobjs of size size.  nobjs may be reduced
  271.   // if it is inconvenient to allocate the requested number.
  272.   static char* _S_chunk_alloc(size_t __size, int& __nobjs);
  273.   // Chunk allocation state.
  274.   static char* _S_start_free;
  275.   static char* _S_end_free;
  276.   static size_t _S_heap_size;
  277. # ifdef __STL_THREADS
  278.     static _STL_mutex_lock _S_node_allocator_lock;
  279. # endif
  280.     // It would be nice to use _STL_auto_lock here.  But we
  281.     // don't need the NULL check.  And we do need a test whether
  282.     // threads have actually been started.
  283.     class _Lock;
  284.     friend class _Lock;
  285.     class _Lock {
  286.         public:
  287.             _Lock() { __NODE_ALLOCATOR_LOCK; }
  288.             ~_Lock() { __NODE_ALLOCATOR_UNLOCK; }
  289.     };
  290. public:
  291.   /* __n must be > 0      */
  292.   static void* allocate(size_t __n)
  293.   {
  294.     void* __ret = 0;
  295.     if (__n > (size_t) _MAX_BYTES) {
  296.       __ret = malloc_alloc::allocate(__n);
  297.     }
  298.     else {
  299.       _Obj* __STL_VOLATILE* __my_free_list
  300.           = _S_free_list + _S_freelist_index(__n);
  301.       // Acquire the lock here with a constructor call.
  302.       // This ensures that it is released in exit or during stack
  303.       // unwinding.
  304. #     ifndef _NOTHREADS
  305.       /*REFERENCED*/
  306.       _Lock __lock_instance;
  307. #     endif
  308.       _Obj* __RESTRICT __result = *__my_free_list;
  309.       if (__result == 0)
  310.         __ret = _S_refill(_S_round_up(__n));
  311.       else {
  312.         *__my_free_list = __result -> _M_free_list_link;
  313.         __ret = __result;
  314.       }
  315.     }
  316.     return __ret;
  317.   };
  318.   /* __p may not be 0 */
  319.   static void deallocate(void* __p, size_t __n)
  320.   {
  321.     if (__n > (size_t) _MAX_BYTES)
  322.       malloc_alloc::deallocate(__p, __n);
  323.     else {
  324.       _Obj* __STL_VOLATILE*  __my_free_list
  325.           = _S_free_list + _S_freelist_index(__n);
  326.       _Obj* __q = (_Obj*)__p;
  327.       // acquire lock
  328. #       ifndef _NOTHREADS
  329.       /*REFERENCED*/
  330.       _Lock __lock_instance;
  331. #       endif /* _NOTHREADS */
  332.       __q -> _M_free_list_link = *__my_free_list;
  333.       *__my_free_list = __q;
  334.       // lock is released here
  335.     }
  336.   }
  337.   static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz);
  338. } ;
  339. typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
  340. typedef __default_alloc_template<false, 0> single_client_alloc;
  341. template <bool __threads, int __inst>
  342. inline bool operator==(const __default_alloc_template<__threads, __inst>&,
  343.                        const __default_alloc_template<__threads, __inst>&)
  344. {
  345.   return true;
  346. }
  347. # ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  348. template <bool __threads, int __inst>
  349. inline bool operator!=(const __default_alloc_template<__threads, __inst>&,
  350.                        const __default_alloc_template<__threads, __inst>&)
  351. {
  352.   return false;
  353. }
  354. # endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  355. /* We allocate memory in large chunks in order to avoid fragmenting     */
  356. /* the malloc heap too much.                                            */
  357. /* We assume that size is properly aligned.                             */
  358. /* We hold the allocation lock.                                         */
  359. template <bool __threads, int __inst>
  360. char*
  361. __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size, 
  362.                                                             int& __nobjs)
  363. {
  364.     char* __result;
  365.     size_t __total_bytes = __size * __nobjs;
  366.     size_t __bytes_left = _S_end_free - _S_start_free;
  367.     if (__bytes_left >= __total_bytes) {
  368.         __result = _S_start_free;
  369.         _S_start_free += __total_bytes;
  370.         return(__result);
  371.     } else if (__bytes_left >= __size) {
  372.         __nobjs = (int)(__bytes_left/__size);
  373.         __total_bytes = __size * __nobjs;
  374.         __result = _S_start_free;
  375.         _S_start_free += __total_bytes;
  376.         return(__result);
  377.     } else {
  378.         size_t __bytes_to_get = 
  379.   2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
  380.         // Try to make use of the left-over piece.
  381.         if (__bytes_left > 0) {
  382.             _Obj* __STL_VOLATILE* __my_free_list =
  383.                         _S_free_list + _S_freelist_index(__bytes_left);
  384.             ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
  385.             *__my_free_list = (_Obj*)_S_start_free;
  386.         }
  387.         _S_start_free = (char*)malloc(__bytes_to_get);
  388.         if (0 == _S_start_free) {
  389.             size_t __i;
  390.             _Obj* __STL_VOLATILE* __my_free_list;
  391.     _Obj* __p;
  392.             // Try to make do with what we have.  That can't
  393.             // hurt.  We do not try smaller requests, since that tends
  394.             // to result in disaster on multi-process machines.
  395.             for (__i = __size;
  396.                  __i <= (size_t) _MAX_BYTES;
  397.                  __i += (size_t) _ALIGN) {
  398.                 __my_free_list = _S_free_list + _S_freelist_index(__i);
  399.                 __p = *__my_free_list;
  400.                 if (0 != __p) {
  401.                     *__my_free_list = __p -> _M_free_list_link;
  402.                     _S_start_free = (char*)__p;
  403.                     _S_end_free = _S_start_free + __i;
  404.                     return(_S_chunk_alloc(__size, __nobjs));
  405.                     // Any leftover piece will eventually make it to the
  406.                     // right free list.
  407.                 }
  408.             }
  409.     _S_end_free = 0; // In case of exception.
  410.             _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get);
  411.             // This should either throw an
  412.             // exception or remedy the situation.  Thus we assume it
  413.             // succeeded.
  414.         }
  415.         _S_heap_size += __bytes_to_get;
  416.         _S_end_free = _S_start_free + __bytes_to_get;
  417.         return(_S_chunk_alloc(__size, __nobjs));
  418.     }
  419. }
  420. /* Returns an object of size __n, and optionally adds to size __n free list.*/
  421. /* We assume that __n is properly aligned.                                */
  422. /* We hold the allocation lock.                                         */
  423. template <bool __threads, int __inst>
  424. void*
  425. __default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
  426. {
  427.     int __nobjs = 20;
  428.     char* __chunk = _S_chunk_alloc(__n, __nobjs);
  429.     _Obj* __STL_VOLATILE* __my_free_list;
  430.     _Obj* __result;
  431.     _Obj* __current_obj;
  432.     _Obj* __next_obj;
  433.     int __i;
  434.     if (1 == __nobjs) return(__chunk);
  435.     __my_free_list = _S_free_list + _S_freelist_index(__n);
  436.     /* Build free list in chunk */
  437.       __result = (_Obj*)__chunk;
  438.       *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
  439.       for (__i = 1; ; __i++) {
  440.         __current_obj = __next_obj;
  441.         __next_obj = (_Obj*)((char*)__next_obj + __n);
  442.         if (__nobjs - 1 == __i) {
  443.             __current_obj -> _M_free_list_link = 0;
  444.             break;
  445.         } else {
  446.             __current_obj -> _M_free_list_link = __next_obj;
  447.         }
  448.       }
  449.     return(__result);
  450. }
  451. template <bool threads, int inst>
  452. void*
  453. __default_alloc_template<threads, inst>::reallocate(void* __p,
  454.                                                     size_t __old_sz,
  455.                                                     size_t __new_sz)
  456. {
  457.     void* __result;
  458.     size_t __copy_sz;
  459.     if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) {
  460.         return(realloc(__p, __new_sz));
  461.     }
  462.     if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p);
  463.     __result = allocate(__new_sz);
  464.     __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
  465.     memcpy(__result, __p, __copy_sz);
  466.     deallocate(__p, __old_sz);
  467.     return(__result);
  468. }
  469. #ifdef __STL_THREADS
  470.     template <bool __threads, int __inst>
  471.     _STL_mutex_lock
  472.     __default_alloc_template<__threads, __inst>::_S_node_allocator_lock
  473.         __STL_MUTEX_INITIALIZER;
  474. #endif
  475. template <bool __threads, int __inst>
  476. char* __default_alloc_template<__threads, __inst>::_S_start_free = 0;
  477. template <bool __threads, int __inst>
  478. char* __default_alloc_template<__threads, __inst>::_S_end_free = 0;
  479. template <bool __threads, int __inst>
  480. size_t __default_alloc_template<__threads, __inst>::_S_heap_size = 0;
  481. template <bool __threads, int __inst>
  482. typename __default_alloc_template<__threads, __inst>::_Obj* __STL_VOLATILE
  483. __default_alloc_template<__threads, __inst> ::_S_free_list[
  484. # if defined(__SUNPRO_CC) || defined(__GNUC__) || defined(__HP_aCC)
  485.     _NFREELISTS
  486. # else
  487.     __default_alloc_template<__threads, __inst>::_NFREELISTS
  488. # endif
  489. ] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
  490. // The 16 zeros are necessary to make version 4.1 of the SunPro
  491. // compiler happy.  Otherwise it appears to allocate too little
  492. // space for the array.
  493. #endif /* ! __USE_MALLOC */
  494. // This implements allocators as specified in the C++ standard.  
  495. //
  496. // Note that standard-conforming allocators use many language features
  497. // that are not yet widely implemented.  In particular, they rely on
  498. // member templates, partial specialization, partial ordering of function
  499. // templates, the typename keyword, and the use of the template keyword
  500. // to refer to a template member of a dependent type.
  501. #ifdef __STL_USE_STD_ALLOCATORS
  502. template <class _Tp>
  503. class allocator {
  504.   typedef alloc _Alloc;          // The underlying allocator.
  505. public:
  506.   typedef size_t     size_type;
  507.   typedef ptrdiff_t  difference_type;
  508.   typedef _Tp*       pointer;
  509.   typedef const _Tp* const_pointer;
  510.   typedef _Tp&       reference;
  511.   typedef const _Tp& const_reference;
  512.   typedef _Tp        value_type;
  513.   template <class _Tp1> struct rebind {
  514.     typedef allocator<_Tp1> other;
  515.   };
  516.   allocator() __STL_NOTHROW {}
  517.   allocator(const allocator&) __STL_NOTHROW {}
  518.   template <class _Tp1> allocator(const allocator<_Tp1>&) __STL_NOTHROW {}
  519.   ~allocator() __STL_NOTHROW {}
  520.   pointer address(reference __x) const { return &__x; }
  521.   const_pointer address(const_reference __x) const { return &__x; }
  522.   // __n is permitted to be 0.  The C++ standard says nothing about what
  523.   // the return value is when __n == 0.
  524.   _Tp* allocate(size_type __n, const void* = 0) {
  525.     return __n != 0 ? static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))) 
  526.                     : 0;
  527.   }
  528.   // __p is not permitted to be a null pointer.
  529.   void deallocate(pointer __p, size_type __n)
  530.     { _Alloc::deallocate(__p, __n * sizeof(_Tp)); }
  531.   size_type max_size() const __STL_NOTHROW 
  532.     { return size_t(-1) / sizeof(_Tp); }
  533.   void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
  534.   void destroy(pointer __p) { __p->~_Tp(); }
  535. };
  536. template<>
  537. class allocator<void> {
  538. public:
  539.   typedef size_t      size_type;
  540.   typedef ptrdiff_t   difference_type;
  541.   typedef void*       pointer;
  542.   typedef const void* const_pointer;
  543.   typedef void        value_type;
  544.   template <class _Tp1> struct rebind {
  545.     typedef allocator<_Tp1> other;
  546.   };
  547. };
  548. template <class _T1, class _T2>
  549. inline bool operator==(const allocator<_T1>&, const allocator<_T2>&) 
  550. {
  551.   return true;
  552. }
  553. template <class _T1, class _T2>
  554. inline bool operator!=(const allocator<_T1>&, const allocator<_T2>&)
  555. {
  556.   return false;
  557. }
  558. // Allocator adaptor to turn an SGI-style allocator (e.g. alloc, malloc_alloc)
  559. // into a standard-conforming allocator.   Note that this adaptor does
  560. // *not* assume that all objects of the underlying alloc class are
  561. // identical, nor does it assume that all of the underlying alloc's
  562. // member functions are static member functions.  Note, also, that 
  563. // __allocator<_Tp, alloc> is essentially the same thing as allocator<_Tp>.
  564. template <class _Tp, class _Alloc>
  565. struct __allocator {
  566.   _Alloc __underlying_alloc;
  567.   typedef size_t    size_type;
  568.   typedef ptrdiff_t difference_type;
  569.   typedef _Tp*       pointer;
  570.   typedef const _Tp* const_pointer;
  571.   typedef _Tp&       reference;
  572.   typedef const _Tp& const_reference;
  573.   typedef _Tp        value_type;
  574.   template <class _Tp1> struct rebind {
  575.     typedef __allocator<_Tp1, _Alloc> other;
  576.   };
  577.   __allocator() __STL_NOTHROW {}
  578.   __allocator(const __allocator& __a) __STL_NOTHROW
  579.     : __underlying_alloc(__a.__underlying_alloc) {}
  580.   template <class _Tp1> 
  581.   __allocator(const __allocator<_Tp1, _Alloc>& __a) __STL_NOTHROW
  582.     : __underlying_alloc(__a.__underlying_alloc) {}
  583.   ~__allocator() __STL_NOTHROW {}
  584.   pointer address(reference __x) const { return &__x; }
  585.   const_pointer address(const_reference __x) const { return &__x; }
  586.   // __n is permitted to be 0.
  587.   _Tp* allocate(size_type __n, const void* = 0) {
  588.     return __n != 0 
  589.         ? static_cast<_Tp*>(__underlying_alloc.allocate(__n * sizeof(_Tp))) 
  590.         : 0;
  591.   }
  592.   // __p is not permitted to be a null pointer.
  593.   void deallocate(pointer __p, size_type __n)
  594.     { __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); }
  595.   size_type max_size() const __STL_NOTHROW 
  596.     { return size_t(-1) / sizeof(_Tp); }
  597.   void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
  598.   void destroy(pointer __p) { __p->~_Tp(); }
  599. };
  600. template <class _Alloc>
  601. class __allocator<void, _Alloc> {
  602.   typedef size_t      size_type;
  603.   typedef ptrdiff_t   difference_type;
  604.   typedef void*       pointer;
  605.   typedef const void* const_pointer;
  606.   typedef void        value_type;
  607.   template <class _Tp1> struct rebind {
  608.     typedef __allocator<_Tp1, _Alloc> other;
  609.   };
  610. };
  611. template <class _Tp, class _Alloc>
  612. inline bool operator==(const __allocator<_Tp, _Alloc>& __a1,
  613.                        const __allocator<_Tp, _Alloc>& __a2)
  614. {
  615.   return __a1.__underlying_alloc == __a2.__underlying_alloc;
  616. }
  617. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  618. template <class _Tp, class _Alloc>
  619. inline bool operator!=(const __allocator<_Tp, _Alloc>& __a1,
  620.                        const __allocator<_Tp, _Alloc>& __a2)
  621. {
  622.   return __a1.__underlying_alloc != __a2.__underlying_alloc;
  623. }
  624. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  625. // Comparison operators for all of the predifined SGI-style allocators.
  626. // This ensures that __allocator<malloc_alloc> (for example) will
  627. // work correctly.
  628. template <int inst>
  629. inline bool operator==(const __malloc_alloc_template<inst>&,
  630.                        const __malloc_alloc_template<inst>&)
  631. {
  632.   return true;
  633. }
  634. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  635. template <int __inst>
  636. inline bool operator!=(const __malloc_alloc_template<__inst>&,
  637.                        const __malloc_alloc_template<__inst>&)
  638. {
  639.   return false;
  640. }
  641. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  642. template <class _Alloc>
  643. inline bool operator==(const debug_alloc<_Alloc>&,
  644.                        const debug_alloc<_Alloc>&) {
  645.   return true;
  646. }
  647. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  648. template <class _Alloc>
  649. inline bool operator!=(const debug_alloc<_Alloc>&,
  650.                        const debug_alloc<_Alloc>&) {
  651.   return false;
  652. }
  653. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  654. // Another allocator adaptor: _Alloc_traits.  This serves two
  655. // purposes.  First, make it possible to write containers that can use
  656. // either SGI-style allocators or standard-conforming allocator.
  657. // Second, provide a mechanism so that containers can query whether or
  658. // not the allocator has distinct instances.  If not, the container
  659. // can avoid wasting a word of memory to store an empty object.
  660. // This adaptor uses partial specialization.  The general case of
  661. // _Alloc_traits<_Tp, _Alloc> assumes that _Alloc is a
  662. // standard-conforming allocator, possibly with non-equal instances
  663. // and non-static members.  (It still behaves correctly even if _Alloc
  664. // has static member and if all instances are equal.  Refinements
  665. // affect performance, not correctness.)
  666. // There are always two members: allocator_type, which is a standard-
  667. // conforming allocator type for allocating objects of type _Tp, and
  668. // _S_instanceless, a static const member of type bool.  If
  669. // _S_instanceless is true, this means that there is no difference
  670. // between any two instances of type allocator_type.  Furthermore, if
  671. // _S_instanceless is true, then _Alloc_traits has one additional
  672. // member: _Alloc_type.  This type encapsulates allocation and
  673. // deallocation of objects of type _Tp through a static interface; it
  674. // has two member functions, whose signatures are
  675. //    static _Tp* allocate(size_t)
  676. //    static void deallocate(_Tp*, size_t)
  677. // The fully general version.
  678. template <class _Tp, class _Allocator>
  679. struct _Alloc_traits
  680. {
  681.   static const bool _S_instanceless = false;
  682.   typedef typename _Allocator::__STL_TEMPLATE rebind<_Tp>::other 
  683.           allocator_type;
  684. };
  685. template <class _Tp, class _Allocator>
  686. const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless;
  687. // The version for the default allocator.
  688. template <class _Tp, class _Tp1>
  689. struct _Alloc_traits<_Tp, allocator<_Tp1> >
  690. {
  691.   static const bool _S_instanceless = true;
  692.   typedef simple_alloc<_Tp, alloc> _Alloc_type;
  693.   typedef allocator<_Tp> allocator_type;
  694. };
  695. // Versions for the predefined SGI-style allocators.
  696. template <class _Tp, int __inst>
  697. struct _Alloc_traits<_Tp, __malloc_alloc_template<__inst> >
  698. {
  699.   static const bool _S_instanceless = true;
  700.   typedef simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type;
  701.   typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
  702. };
  703. template <class _Tp, bool __threads, int __inst>
  704. struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> >
  705. {
  706.   static const bool _S_instanceless = true;
  707.   typedef simple_alloc<_Tp, __default_alloc_template<__threads, __inst> > 
  708.           _Alloc_type;
  709.   typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> > 
  710.           allocator_type;
  711. };
  712. template <class _Tp, class _Alloc>
  713. struct _Alloc_traits<_Tp, debug_alloc<_Alloc> >
  714. {
  715.   static const bool _S_instanceless = true;
  716.   typedef simple_alloc<_Tp, debug_alloc<_Alloc> > _Alloc_type;
  717.   typedef __allocator<_Tp, debug_alloc<_Alloc> > allocator_type;
  718. };
  719. // Versions for the __allocator adaptor used with the predefined
  720. // SGI-style allocators.
  721. template <class _Tp, class _Tp1, int __inst>
  722. struct _Alloc_traits<_Tp, 
  723.                      __allocator<_Tp1, __malloc_alloc_template<__inst> > >
  724. {
  725.   static const bool _S_instanceless = true;
  726.   typedef simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type;
  727.   typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
  728. };
  729. template <class _Tp, class _Tp1, bool __thr, int __inst>
  730. struct _Alloc_traits<_Tp, 
  731.                       __allocator<_Tp1, 
  732.                                   __default_alloc_template<__thr, __inst> > >
  733. {
  734.   static const bool _S_instanceless = true;
  735.   typedef simple_alloc<_Tp, __default_alloc_template<__thr,__inst> > 
  736.           _Alloc_type;
  737.   typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> > 
  738.           allocator_type;
  739. };
  740. template <class _Tp, class _Tp1, class _Alloc>
  741. struct _Alloc_traits<_Tp, __allocator<_Tp1, debug_alloc<_Alloc> > >
  742. {
  743.   static const bool _S_instanceless = true;
  744.   typedef simple_alloc<_Tp, debug_alloc<_Alloc> > _Alloc_type;
  745.   typedef __allocator<_Tp, debug_alloc<_Alloc> > allocator_type;
  746. };
  747. #endif /* __STL_USE_STD_ALLOCATORS */
  748. #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
  749. #pragma reset woff 1174
  750. #endif
  751. __STL_END_NAMESPACE
  752. #undef __PRIVATE
  753. #endif /* __SGI_STL_INTERNAL_ALLOC_H */
  754. // Local Variables:
  755. // mode:C++
  756. // End: