Whole document tree
    

Whole document tree

stl_alloc.h Source File
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

stl_alloc.h

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

Generated on Mon Apr 8 03:11:37 2002 for libstdc++-v3 Source by doxygen1.2.15