stl_alloc.h

00001 /*
00002  * Copyright (c) 1996-1997
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Permission to use, copy, modify, distribute and sell this software
00006  * and its documentation for any purpose is hereby granted without fee,
00007  * provided that the above copyright notice appear in all copies and
00008  * that both that copyright notice and this permission notice appear
00009  * in supporting documentation.  Silicon Graphics makes no
00010  * representations about the suitability of this software for any
00011  * purpose.  It is provided "as is" without express or implied warranty.
00012  */
00013 
00014 /* NOTE: This is an internal header file, included by other STL headers.
00015  *   You should not attempt to use it directly.
00016  */
00017 
00018 #ifndef __SGI_STL_INTERNAL_ALLOC_H
00019 #define __SGI_STL_INTERNAL_ALLOC_H
00020 
00021 #ifdef __SUNPRO_CC
00022 #  define __PRIVATE public
00023    // Extra access restrictions prevent us from really making some things
00024    // private.
00025 #else
00026 #  define __PRIVATE private
00027 #endif
00028 
00029 #ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
00030 #  define __USE_MALLOC
00031 #endif
00032 
00033 
00034 // This implements some standard node allocators.  These are
00035 // NOT the same as the allocators in the C++ draft standard or in
00036 // in the original STL.  They do not encapsulate different pointer
00037 // types; indeed we assume that there is only one pointer type.
00038 // The allocation primitives are intended to allocate individual objects,
00039 // not larger arenas as with the original STL allocators.
00040 
00041 #ifndef __THROW_BAD_ALLOC
00042 # ifndef UNDER_CE
00043 #  if defined(__STL_NO_BAD_ALLOC) || !defined(__STL_USE_EXCEPTIONS)
00044 #    include <stdio.h>
00045 #    include <stdlib.h>
00046 #    define __THROW_BAD_ALLOC fprintf(stderr, "out of memory\n"); exit(1)
00047 #  else /* Standard conforming out-of-memory handling */
00048 #    include <new>
00049 #    define __THROW_BAD_ALLOC throw std::bad_alloc()
00050 #  endif
00051 # endif /* UNDER_CE */
00052 #endif
00053 
00054 #ifndef UNDER_CE
00055 #include <stddef.h>
00056 #else
00057 #include <wce_defs.h>
00058 #endif /* UNDER_CE */
00059 #include <stdlib.h>
00060 #include <string.h>
00061 #ifndef UNDER_CE
00062 #include <assert.h>
00063 #endif
00064 #ifndef __RESTRICT
00065 #  define __RESTRICT
00066 #endif
00067 
00068 #ifdef __STL_THREADS
00069 # include <stl_threads.h>
00070 # define __NODE_ALLOCATOR_THREADS true
00071 # ifdef __STL_SGI_THREADS
00072   // We test whether threads are in use before locking.
00073   // Perhaps this should be moved into stl_threads.h, but that
00074   // probably makes it harder to avoid the procedure call when
00075   // it isn't needed.
00076     extern "C" {
00077       extern int __us_rsthread_malloc;
00078     }
00079         // The above is copied from malloc.h.  Including <malloc.h>
00080         // would be cleaner but fails with certain levels of standard
00081         // conformance.
00082 #   define __NODE_ALLOCATOR_LOCK if (threads && __us_rsthread_malloc) \
00083                 { _S_node_allocator_lock._M_acquire_lock(); }
00084 #   define __NODE_ALLOCATOR_UNLOCK if (threads && __us_rsthread_malloc) \
00085                 { _S_node_allocator_lock._M_release_lock(); }
00086 # else /* !__STL_SGI_THREADS */
00087 #   define __NODE_ALLOCATOR_LOCK \
00088         { if (threads) _S_node_allocator_lock._M_acquire_lock(); }
00089 #   define __NODE_ALLOCATOR_UNLOCK \
00090         { if (threads) _S_node_allocator_lock._M_release_lock(); }
00091 # endif
00092 #else
00093 //  Thread-unsafe
00094 #   define __NODE_ALLOCATOR_LOCK
00095 #   define __NODE_ALLOCATOR_UNLOCK
00096 #   define __NODE_ALLOCATOR_THREADS false
00097 #endif
00098 
00099 __STL_BEGIN_NAMESPACE
00100 
00101 #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
00102 #pragma set woff 1174
00103 #endif
00104 
00105 // Malloc-based allocator.  Typically slower than default alloc below.
00106 // Typically thread-safe and more storage efficient.
00107 #ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
00108 # ifdef __DECLARE_GLOBALS_HERE
00109     void (* __malloc_alloc_oom_handler)() = 0;
00110     // g++ 2.7.2 does not handle static template data members.
00111 # else
00112     extern void (* __malloc_alloc_oom_handler)();
00113 # endif
00114 #endif
00115 
00116 template <int __inst>
00117 class __malloc_alloc_template {
00118 
00119 private:
00120 
00121   static void* _S_oom_malloc(size_t);
00122   static void* _S_oom_realloc(void*, size_t);
00123 
00124 #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
00125   static void (* __malloc_alloc_oom_handler)();
00126 #endif
00127 
00128 public:
00129 
00130   static void* allocate(size_t __n)
00131   {
00132     void* __result = malloc(__n);
00133     if (0 == __result) __result = _S_oom_malloc(__n);
00134     return __result;
00135   }
00136 
00137   static void deallocate(void* __p, size_t /* __n */)
00138   {
00139     free(__p);
00140   }
00141 
00142   static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz)
00143   {
00144     void* __result = realloc(__p, __new_sz);
00145     if (0 == __result) __result = _S_oom_realloc(__p, __new_sz);
00146     return __result;
00147   }
00148 
00149   static void (* __set_malloc_handler(void (*__f)()))()
00150   {
00151     void (* __old)() = __malloc_alloc_oom_handler;
00152     __malloc_alloc_oom_handler = __f;
00153     return(__old);
00154   }
00155 
00156 };
00157 
00158 // malloc_alloc out-of-memory handling
00159 
00160 #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
00161 template <int __inst>
00162 void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0;
00163 #endif
00164 
00165 template <int __inst>
00166 void*
00167 __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
00168 {
00169     void (* __my_malloc_handler)();
00170     void* __result;
00171 
00172     for (;;) {
00173         __my_malloc_handler = __malloc_alloc_oom_handler;
00174         if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; }
00175         (*__my_malloc_handler)();
00176         __result = malloc(__n);
00177         if (__result) return(__result);
00178     }
00179 }
00180 
00181 template <int __inst>
00182 void* __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n)
00183 {
00184     void (* __my_malloc_handler)();
00185     void* __result;
00186 
00187     for (;;) {
00188         __my_malloc_handler = __malloc_alloc_oom_handler;
00189         if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; }
00190         (*__my_malloc_handler)();
00191         __result = realloc(__p, __n);
00192         if (__result) return(__result);
00193     }
00194 }
00195 
00196 typedef __malloc_alloc_template<0> malloc_alloc;
00197 
00198 template<class _Tp, class _Alloc>
00199 class simple_alloc {
00200 
00201 public:
00202     static _Tp* allocate(size_t __n)
00203       { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
00204     static _Tp* allocate(void)
00205       { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }
00206     static void deallocate(_Tp* __p, size_t __n)
00207       { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }
00208     static void deallocate(_Tp* __p)
00209       { _Alloc::deallocate(__p, sizeof (_Tp)); }
00210 };
00211 
00212 // Allocator adaptor to check size arguments for debugging.
00213 // Reports errors using assert.  Checking can be disabled with
00214 // NDEBUG, but it's far better to just use the underlying allocator
00215 // instead when no checking is desired.
00216 // There is some evidence that this can confuse Purify.
00217 template <class _Alloc>
00218 class debug_alloc {
00219 
00220 private:
00221 
00222   enum {_S_extra = 8};  // Size of space used to store size.  Note
00223                         // that this must be large enough to preserve
00224                         // alignment.
00225 
00226 public:
00227 
00228   static void* allocate(size_t __n)
00229   {
00230     char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra);
00231     *(size_t*)__result = __n;
00232     return __result + (int) _S_extra;
00233   }
00234 
00235   static void deallocate(void* __p, size_t __n)
00236   {
00237     char* __real_p = (char*)__p - (int) _S_extra;
00238     assert(*(size_t*)__real_p == __n);
00239     _Alloc::deallocate(__real_p, __n + (int) _S_extra);
00240   }
00241 
00242   static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz)
00243   {
00244     char* __real_p = (char*)__p - (int) _S_extra;
00245     assert(*(size_t*)__real_p == __old_sz);
00246     char* __result = (char*)
00247       _Alloc::reallocate(__real_p, __old_sz + (int) _S_extra,
00248                                    __new_sz + (int) _S_extra);
00249     *(size_t*)__result = __new_sz;
00250     return __result + (int) _S_extra;
00251   }
00252 
00253 };
00254 
00255 
00256 # ifdef __USE_MALLOC
00257 
00258 typedef malloc_alloc alloc;
00259 typedef malloc_alloc single_client_alloc;
00260 
00261 # else
00262 
00263 
00264 // Default node allocator.
00265 // With a reasonable compiler, this should be roughly as fast as the
00266 // original STL class-specific allocators, but with less fragmentation.
00267 // Default_alloc_template parameters are experimental and MAY
00268 // DISAPPEAR in the future.  Clients should just use alloc for now.
00269 //
00270 // Important implementation properties:
00271 // 1. If the client request an object of size > _MAX_BYTES, the resulting
00272 //    object will be obtained directly from malloc.
00273 // 2. In all other cases, we allocate an object of size exactly
00274 //    _S_round_up(requested_size).  Thus the client has enough size
00275 //    information that we can return the object to the proper free list
00276 //    without permanently losing part of the object.
00277 //
00278 
00279 // The first template parameter specifies whether more than one thread
00280 // may use this allocator.  It is safe to allocate an object from
00281 // one instance of a default_alloc and deallocate it with another
00282 // one.  This effectively transfers its ownership to the second one.
00283 // This may have undesirable effects on reference locality.
00284 // The second parameter is unreferenced and serves only to allow the
00285 // creation of multiple default_alloc instances.
00286 // Node that containers built on different allocator instances have
00287 // different types, limiting the utility of this approach.
00288 
00289 #if defined(__SUNPRO_CC) || defined(__GNUC__)
00290 // breaks if we make these template class members:
00291   enum {_ALIGN = 8};
00292   enum {_MAX_BYTES = 128};
00293   enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN
00294 #endif
00295 
00296 template <bool threads, int inst>
00297 class __default_alloc_template {
00298 
00299 private:
00300   // Really we should use static const int x = N
00301   // instead of enum { x = N }, but few compilers accept the former.
00302 #if ! (defined(__SUNPRO_CC) || defined(__GNUC__))
00303     enum {_ALIGN = 8};
00304     enum {_MAX_BYTES = 128};
00305     enum {_NFREELISTS = 16}; // _MAX_BYTES/_ALIGN
00306 # endif
00307   static size_t
00308   _S_round_up(size_t __bytes) 
00309     { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); }
00310 
00311 __PRIVATE:
00312   union _Obj {
00313         union _Obj* _M_free_list_link;
00314         char _M_client_data[1];    /* The client sees this.        */
00315   };
00316 private:
00317 # if defined(__SUNPRO_CC) || defined(__GNUC__) || defined(__HP_aCC)
00318     static _Obj* __STL_VOLATILE _S_free_list[]; 
00319         // Specifying a size results in duplicate def for 4.1
00320 # else
00321     static _Obj* __STL_VOLATILE _S_free_list[_NFREELISTS]; 
00322 # endif
00323   static  size_t _S_freelist_index(size_t __bytes) {
00324         return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1);
00325   }
00326 
00327   // Returns an object of size __n, and optionally adds to size __n free list.
00328   static void* _S_refill(size_t __n);
00329   // Allocates a chunk for nobjs of size size.  nobjs may be reduced
00330   // if it is inconvenient to allocate the requested number.
00331   static char* _S_chunk_alloc(size_t __size, int& __nobjs);
00332 
00333   // Chunk allocation state.
00334   static char* _S_start_free;
00335   static char* _S_end_free;
00336   static size_t _S_heap_size;
00337 
00338 # ifdef __STL_THREADS
00339     static _STL_mutex_lock _S_node_allocator_lock;
00340 # endif
00341 
00342     // It would be nice to use _STL_auto_lock here.  But we
00343     // don't need the NULL check.  And we do need a test whether
00344     // threads have actually been started.
00345     class _Lock;
00346     friend class _Lock;
00347     class _Lock {
00348         public:
00349             _Lock() { __NODE_ALLOCATOR_LOCK; }
00350             ~_Lock() { __NODE_ALLOCATOR_UNLOCK; }
00351     };
00352 
00353 public:
00354 
00355   /* __n must be > 0      */
00356   static void* allocate(size_t __n)
00357   {
00358     void* __ret = 0;
00359 
00360     if (__n > (size_t) _MAX_BYTES) {
00361       __ret = malloc_alloc::allocate(__n);
00362     }
00363     else {
00364       _Obj* __STL_VOLATILE* __my_free_list
00365           = _S_free_list + _S_freelist_index(__n);
00366       // Acquire the lock here with a constructor call.
00367       // This ensures that it is released in exit or during stack
00368       // unwinding.
00369 #     ifndef _NOTHREADS
00370       /*REFERENCED*/
00371       _Lock __lock_instance;
00372 #     endif
00373       _Obj* __RESTRICT __result = *__my_free_list;
00374       if (__result == 0)
00375         __ret = _S_refill(_S_round_up(__n));
00376       else {
00377         *__my_free_list = __result -> _M_free_list_link;
00378         __ret = __result;
00379       }
00380     }
00381 
00382     return __ret;
00383   };
00384 
00385   /* __p may not be 0 */
00386   static void deallocate(void* __p, size_t __n)
00387   {
00388     if (__n > (size_t) _MAX_BYTES)
00389       malloc_alloc::deallocate(__p, __n);
00390     else {
00391       _Obj* __STL_VOLATILE*  __my_free_list
00392           = _S_free_list + _S_freelist_index(__n);
00393       _Obj* __q = (_Obj*)__p;
00394 
00395       // acquire lock
00396 #       ifndef _NOTHREADS
00397       /*REFERENCED*/
00398       _Lock __lock_instance;
00399 #       endif /* _NOTHREADS */
00400       __q -> _M_free_list_link = *__my_free_list;
00401       *__my_free_list = __q;
00402       // lock is released here
00403     }
00404   }
00405 
00406   static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz);
00407 
00408 } ;
00409 
00410 typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
00411 typedef __default_alloc_template<false, 0> single_client_alloc;
00412 
00413 template <bool __threads, int __inst>
00414 inline bool operator==(const __default_alloc_template<__threads, __inst>&,
00415                        const __default_alloc_template<__threads, __inst>&)
00416 {
00417   return true;
00418 }
00419 
00420 # ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
00421 template <bool __threads, int __inst>
00422 inline bool operator!=(const __default_alloc_template<__threads, __inst>&,
00423                        const __default_alloc_template<__threads, __inst>&)
00424 {
00425   return false;
00426 }
00427 # endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
00428 
00429 
00430 
00431 /* We allocate memory in large chunks in order to avoid fragmenting     */
00432 /* the malloc heap too much.                                            */
00433 /* We assume that size is properly aligned.                             */
00434 /* We hold the allocation lock.                                         */
00435 template <bool __threads, int __inst>
00436 char*
00437 __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size, 
00438                                                             int& __nobjs)
00439 {
00440     char* __result;
00441     size_t __total_bytes = __size * __nobjs;
00442     size_t __bytes_left = _S_end_free - _S_start_free;
00443 
00444     if (__bytes_left >= __total_bytes) {
00445         __result = _S_start_free;
00446         _S_start_free += __total_bytes;
00447         return(__result);
00448     } else if (__bytes_left >= __size) {
00449         __nobjs = (int)(__bytes_left/__size);
00450         __total_bytes = __size * __nobjs;
00451         __result = _S_start_free;
00452         _S_start_free += __total_bytes;
00453         return(__result);
00454     } else {
00455         size_t __bytes_to_get = 
00456           2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
00457         // Try to make use of the left-over piece.
00458         if (__bytes_left > 0) {
00459             _Obj* __STL_VOLATILE* __my_free_list =
00460                         _S_free_list + _S_freelist_index(__bytes_left);
00461 
00462             ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
00463             *__my_free_list = (_Obj*)_S_start_free;
00464         }
00465         _S_start_free = (char*)malloc(__bytes_to_get);
00466         if (0 == _S_start_free) {
00467             size_t __i;
00468             _Obj* __STL_VOLATILE* __my_free_list;
00469             _Obj* __p;
00470             // Try to make do with what we have.  That can't
00471             // hurt.  We do not try smaller requests, since that tends
00472             // to result in disaster on multi-process machines.
00473             for (__i = __size;
00474                  __i <= (size_t) _MAX_BYTES;
00475                  __i += (size_t) _ALIGN) {
00476                 __my_free_list = _S_free_list + _S_freelist_index(__i);
00477                 __p = *__my_free_list;
00478                 if (0 != __p) {
00479                     *__my_free_list = __p -> _M_free_list_link;
00480                     _S_start_free = (char*)__p;
00481                     _S_end_free = _S_start_free + __i;
00482                     return(_S_chunk_alloc(__size, __nobjs));
00483                     // Any leftover piece will eventually make it to the
00484                     // right free list.
00485                 }
00486             }
00487             _S_end_free = 0;    // In case of exception.
00488             _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get);
00489             // This should either throw an
00490             // exception or remedy the situation.  Thus we assume it
00491             // succeeded.
00492         }
00493         _S_heap_size += __bytes_to_get;
00494         _S_end_free = _S_start_free + __bytes_to_get;
00495         return(_S_chunk_alloc(__size, __nobjs));
00496     }
00497 }
00498 
00499 
00500 /* Returns an object of size __n, and optionally adds to size __n free list.*/
00501 /* We assume that __n is properly aligned.                                */
00502 /* We hold the allocation lock.                                         */
00503 template <bool __threads, int __inst>
00504 void*
00505 __default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
00506 {
00507     int __nobjs = 20;
00508     char* __chunk = _S_chunk_alloc(__n, __nobjs);
00509     _Obj* __STL_VOLATILE* __my_free_list;
00510     _Obj* __result;
00511     _Obj* __current_obj;
00512     _Obj* __next_obj;
00513     int __i;
00514 
00515     if (1 == __nobjs) return(__chunk);
00516     __my_free_list = _S_free_list + _S_freelist_index(__n);
00517 
00518     /* Build free list in chunk */
00519       __result = (_Obj*)__chunk;
00520       *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
00521       for (__i = 1; ; __i++) {
00522         __current_obj = __next_obj;
00523         __next_obj = (_Obj*)((char*)__next_obj + __n);
00524         if (__nobjs - 1 == __i) {
00525             __current_obj -> _M_free_list_link = 0;
00526             break;
00527         } else {
00528             __current_obj -> _M_free_list_link = __next_obj;
00529         }
00530       }
00531     return(__result);
00532 }
00533 
00534 template <bool threads, int inst>
00535 void*
00536 __default_alloc_template<threads, inst>::reallocate(void* __p,
00537                                                     size_t __old_sz,
00538                                                     size_t __new_sz)
00539 {
00540     void* __result;
00541     size_t __copy_sz;
00542 
00543     if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) {
00544         return(realloc(__p, __new_sz));
00545     }
00546     if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p);
00547     __result = allocate(__new_sz);
00548     __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
00549     memcpy(__result, __p, __copy_sz);
00550     deallocate(__p, __old_sz);
00551     return(__result);
00552 }
00553 
00554 #ifdef __STL_THREADS
00555     template <bool __threads, int __inst>
00556     _STL_mutex_lock
00557     __default_alloc_template<__threads, __inst>::_S_node_allocator_lock
00558         __STL_MUTEX_INITIALIZER;
00559 #endif
00560 
00561 
00562 template <bool __threads, int __inst>
00563 char* __default_alloc_template<__threads, __inst>::_S_start_free = 0;
00564 
00565 template <bool __threads, int __inst>
00566 char* __default_alloc_template<__threads, __inst>::_S_end_free = 0;
00567 
00568 template <bool __threads, int __inst>
00569 size_t __default_alloc_template<__threads, __inst>::_S_heap_size = 0;
00570 
00571 template <bool __threads, int __inst>
00572 typename __default_alloc_template<__threads, __inst>::_Obj* __STL_VOLATILE
00573 __default_alloc_template<__threads, __inst> ::_S_free_list[
00574 # if defined(__SUNPRO_CC) || defined(__GNUC__) || defined(__HP_aCC)
00575     _NFREELISTS
00576 # else
00577     __default_alloc_template<__threads, __inst>::_NFREELISTS
00578 # endif
00579 ] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
00580 // The 16 zeros are necessary to make version 4.1 of the SunPro
00581 // compiler happy.  Otherwise it appears to allocate too little
00582 // space for the array.
00583 
00584 #endif /* ! __USE_MALLOC */
00585 
00586 // This implements allocators as specified in the C++ standard.  
00587 //
00588 // Note that standard-conforming allocators use many language features
00589 // that are not yet widely implemented.  In particular, they rely on
00590 // member templates, partial specialization, partial ordering of function
00591 // templates, the typename keyword, and the use of the template keyword
00592 // to refer to a template member of a dependent type.
00593 
00594 #ifdef __STL_USE_STD_ALLOCATORS
00595 
00596 template <class _Tp>
00597 class allocator {
00598   typedef alloc _Alloc;          // The underlying allocator.
00599 public:
00600   typedef size_t     size_type;
00601   typedef ptrdiff_t  difference_type;
00602   typedef _Tp*       pointer;
00603   typedef const _Tp* const_pointer;
00604   typedef _Tp&       reference;
00605   typedef const _Tp& const_reference;
00606   typedef _Tp        value_type;
00607 
00608   template <class _Tp1> struct rebind {
00609     typedef allocator<_Tp1> other;
00610   };
00611 
00612   allocator() __STL_NOTHROW {}
00613   allocator(const allocator&) __STL_NOTHROW {}
00614   template <class _Tp1> allocator(const allocator<_Tp1>&) __STL_NOTHROW {}
00615   ~allocator() __STL_NOTHROW {}
00616 
00617   pointer address(reference __x) const { return &__x; }
00618   const_pointer address(const_reference __x) const { return &__x; }
00619 
00620   // __n is permitted to be 0.  The C++ standard says nothing about what
00621   // the return value is when __n == 0.
00622   _Tp* allocate(size_type __n, const void* = 0) {
00623     return __n != 0 ? static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp))) 
00624                     : 0;
00625   }
00626 
00627   // __p is not permitted to be a null pointer.
00628   void deallocate(pointer __p, size_type __n)
00629     { _Alloc::deallocate(__p, __n * sizeof(_Tp)); }
00630 
00631   size_type max_size() const __STL_NOTHROW 
00632     { return size_t(-1) / sizeof(_Tp); }
00633 
00634   void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
00635   void destroy(pointer __p) { __p->~_Tp(); }
00636 };
00637 
00638 template<>
00639 class allocator<void> {
00640 public:
00641   typedef size_t      size_type;
00642   typedef ptrdiff_t   difference_type;
00643   typedef void*       pointer;
00644   typedef const void* const_pointer;
00645   typedef void        value_type;
00646 
00647   template <class _Tp1> struct rebind {
00648     typedef allocator<_Tp1> other;
00649   };
00650 };
00651 
00652 
00653 template <class _T1, class _T2>
00654 inline bool operator==(const allocator<_T1>&, const allocator<_T2>&) 
00655 {
00656   return true;
00657 }
00658 
00659 template <class _T1, class _T2>
00660 inline bool operator!=(const allocator<_T1>&, const allocator<_T2>&)
00661 {
00662   return false;
00663 }
00664 
00665 // Allocator adaptor to turn an SGI-style allocator (e.g. alloc, malloc_alloc)
00666 // into a standard-conforming allocator.   Note that this adaptor does
00667 // *not* assume that all objects of the underlying alloc class are
00668 // identical, nor does it assume that all of the underlying alloc's
00669 // member functions are static member functions.  Note, also, that 
00670 // __allocator<_Tp, alloc> is essentially the same thing as allocator<_Tp>.
00671 
00672 template <class _Tp, class _Alloc>
00673 struct __allocator {
00674   _Alloc __underlying_alloc;
00675 
00676   typedef size_t    size_type;
00677   typedef ptrdiff_t difference_type;
00678   typedef _Tp*       pointer;
00679   typedef const _Tp* const_pointer;
00680   typedef _Tp&       reference;
00681   typedef const _Tp& const_reference;
00682   typedef _Tp        value_type;
00683 
00684   template <class _Tp1> struct rebind {
00685     typedef __allocator<_Tp1, _Alloc> other;
00686   };
00687 
00688   __allocator() __STL_NOTHROW {}
00689   __allocator(const __allocator& __a) __STL_NOTHROW
00690     : __underlying_alloc(__a.__underlying_alloc) {}
00691   template <class _Tp1> 
00692   __allocator(const __allocator<_Tp1, _Alloc>& __a) __STL_NOTHROW
00693     : __underlying_alloc(__a.__underlying_alloc) {}
00694   ~__allocator() __STL_NOTHROW {}
00695 
00696   pointer address(reference __x) const { return &__x; }
00697   const_pointer address(const_reference __x) const { return &__x; }
00698 
00699   // __n is permitted to be 0.
00700   _Tp* allocate(size_type __n, const void* = 0) {
00701     return __n != 0 
00702         ? static_cast<_Tp*>(__underlying_alloc.allocate(__n * sizeof(_Tp))) 
00703         : 0;
00704   }
00705 
00706   // __p is not permitted to be a null pointer.
00707   void deallocate(pointer __p, size_type __n)
00708     { __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); }
00709 
00710   size_type max_size() const __STL_NOTHROW 
00711     { return size_t(-1) / sizeof(_Tp); }
00712 
00713   void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
00714   void destroy(pointer __p) { __p->~_Tp(); }
00715 };
00716 
00717 template <class _Alloc>
00718 class __allocator<void, _Alloc> {
00719   typedef size_t      size_type;
00720   typedef ptrdiff_t   difference_type;
00721   typedef void*       pointer;
00722   typedef const void* const_pointer;
00723   typedef void        value_type;
00724 
00725   template <class _Tp1> struct rebind {
00726     typedef __allocator<_Tp1, _Alloc> other;
00727   };
00728 };
00729 
00730 template <class _Tp, class _Alloc>
00731 inline bool operator==(const __allocator<_Tp, _Alloc>& __a1,
00732                        const __allocator<_Tp, _Alloc>& __a2)
00733 {
00734   return __a1.__underlying_alloc == __a2.__underlying_alloc;
00735 }
00736 
00737 #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
00738 template <class _Tp, class _Alloc>
00739 inline bool operator!=(const __allocator<_Tp, _Alloc>& __a1,
00740                        const __allocator<_Tp, _Alloc>& __a2)
00741 {
00742   return __a1.__underlying_alloc != __a2.__underlying_alloc;
00743 }
00744 #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
00745 
00746 // Comparison operators for all of the predifined SGI-style allocators.
00747 // This ensures that __allocator<malloc_alloc> (for example) will
00748 // work correctly.
00749 
00750 template <int inst>
00751 inline bool operator==(const __malloc_alloc_template<inst>&,
00752                        const __malloc_alloc_template<inst>&)
00753 {
00754   return true;
00755 }
00756 
00757 #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
00758 template <int __inst>
00759 inline bool operator!=(const __malloc_alloc_template<__inst>&,
00760                        const __malloc_alloc_template<__inst>&)
00761 {
00762   return false;
00763 }
00764 #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
00765 
00766 
00767 template <class _Alloc>
00768 inline bool operator==(const debug_alloc<_Alloc>&,
00769                        const debug_alloc<_Alloc>&) {
00770   return true;
00771 }
00772 
00773 #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
00774 template <class _Alloc>
00775 inline bool operator!=(const debug_alloc<_Alloc>&,
00776                        const debug_alloc<_Alloc>&) {
00777   return false;
00778 }
00779 #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
00780 
00781 // Another allocator adaptor: _Alloc_traits.  This serves two
00782 // purposes.  First, make it possible to write containers that can use
00783 // either SGI-style allocators or standard-conforming allocator.
00784 // Second, provide a mechanism so that containers can query whether or
00785 // not the allocator has distinct instances.  If not, the container
00786 // can avoid wasting a word of memory to store an empty object.
00787 
00788 // This adaptor uses partial specialization.  The general case of
00789 // _Alloc_traits<_Tp, _Alloc> assumes that _Alloc is a
00790 // standard-conforming allocator, possibly with non-equal instances
00791 // and non-static members.  (It still behaves correctly even if _Alloc
00792 // has static member and if all instances are equal.  Refinements
00793 // affect performance, not correctness.)
00794 
00795 // There are always two members: allocator_type, which is a standard-
00796 // conforming allocator type for allocating objects of type _Tp, and
00797 // _S_instanceless, a static const member of type bool.  If
00798 // _S_instanceless is true, this means that there is no difference
00799 // between any two instances of type allocator_type.  Furthermore, if
00800 // _S_instanceless is true, then _Alloc_traits has one additional
00801 // member: _Alloc_type.  This type encapsulates allocation and
00802 // deallocation of objects of type _Tp through a static interface; it
00803 // has two member functions, whose signatures are
00804 //    static _Tp* allocate(size_t)
00805 //    static void deallocate(_Tp*, size_t)
00806 
00807 // The fully general version.
00808 
00809 template <class _Tp, class _Allocator>
00810 struct _Alloc_traits
00811 {
00812   static const bool _S_instanceless = false;
00813   typedef typename _Allocator::__STL_TEMPLATE rebind<_Tp>::other 
00814           allocator_type;
00815 };
00816 
00817 template <class _Tp, class _Allocator>
00818 const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless;
00819 
00820 // The version for the default allocator.
00821 
00822 template <class _Tp, class _Tp1>
00823 struct _Alloc_traits<_Tp, allocator<_Tp1> >
00824 {
00825   static const bool _S_instanceless = true;
00826   typedef simple_alloc<_Tp, alloc> _Alloc_type;
00827   typedef allocator<_Tp> allocator_type;
00828 };
00829 
00830 // Versions for the predefined SGI-style allocators.
00831 
00832 template <class _Tp, int __inst>
00833 struct _Alloc_traits<_Tp, __malloc_alloc_template<__inst> >
00834 {
00835   static const bool _S_instanceless = true;
00836   typedef simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type;
00837   typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
00838 };
00839 
00840 template <class _Tp, bool __threads, int __inst>
00841 struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> >
00842 {
00843   static const bool _S_instanceless = true;
00844   typedef simple_alloc<_Tp, __default_alloc_template<__threads, __inst> > 
00845           _Alloc_type;
00846   typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> > 
00847           allocator_type;
00848 };
00849 
00850 template <class _Tp, class _Alloc>
00851 struct _Alloc_traits<_Tp, debug_alloc<_Alloc> >
00852 {
00853   static const bool _S_instanceless = true;
00854   typedef simple_alloc<_Tp, debug_alloc<_Alloc> > _Alloc_type;
00855   typedef __allocator<_Tp, debug_alloc<_Alloc> > allocator_type;
00856 };
00857 
00858 // Versions for the __allocator adaptor used with the predefined
00859 // SGI-style allocators.
00860 
00861 template <class _Tp, class _Tp1, int __inst>
00862 struct _Alloc_traits<_Tp, 
00863                      __allocator<_Tp1, __malloc_alloc_template<__inst> > >
00864 {
00865   static const bool _S_instanceless = true;
00866   typedef simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type;
00867   typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
00868 };
00869 
00870 template <class _Tp, class _Tp1, bool __thr, int __inst>
00871 struct _Alloc_traits<_Tp, 
00872                       __allocator<_Tp1, 
00873                                   __default_alloc_template<__thr, __inst> > >
00874 {
00875   static const bool _S_instanceless = true;
00876   typedef simple_alloc<_Tp, __default_alloc_template<__thr,__inst> > 
00877           _Alloc_type;
00878   typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> > 
00879           allocator_type;
00880 };
00881 
00882 template <class _Tp, class _Tp1, class _Alloc>
00883 struct _Alloc_traits<_Tp, __allocator<_Tp1, debug_alloc<_Alloc> > >
00884 {
00885   static const bool _S_instanceless = true;
00886   typedef simple_alloc<_Tp, debug_alloc<_Alloc> > _Alloc_type;
00887   typedef __allocator<_Tp, debug_alloc<_Alloc> > allocator_type;
00888 };
00889 
00890 
00891 #endif /* __STL_USE_STD_ALLOCATORS */
00892 
00893 #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
00894 #pragma reset woff 1174
00895 #endif
00896 
00897 __STL_END_NAMESPACE
00898 
00899 #undef __PRIVATE
00900 
00901 #endif /* __SGI_STL_INTERNAL_ALLOC_H */
00902 
00903 // Local Variables:
00904 // mode:C++
00905 // End:

Generated on Mon Jun 5 10:20:44 2006 for Intelligence.kdevelop by  doxygen 1.4.6