stl_alloc.h
上传用户:kellyonhid
上传日期:2013-10-12
资源大小:932k
文件大小:32k
源码类别:

3D图形编程

开发平台:

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. #if 0
  35. #   include <new>
  36. #   define __THROW_BAD_ALLOC throw bad_alloc()
  37. #elif !defined(__THROW_BAD_ALLOC)
  38. #   include <iostream.h>
  39. #   define __THROW_BAD_ALLOC cerr << "out of memory" << endl; exit(1)
  40. #endif
  41. #ifdef __STL_WIN32THREADS
  42. #   include <windows.h>
  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. #if !defined(_PTHREADS) && !defined(_NOTHREADS) 
  52.  && !defined(__STL_SGI_THREADS) && !defined(__STL_WIN32THREADS)
  53. #   define _NOTHREADS
  54. #endif
  55. # ifdef _PTHREADS
  56.     // POSIX Threads
  57.     // This is dubious, since this is likely to be a high contention
  58.     // lock.   Performance may not be adequate.
  59. #   include <pthread.h>
  60. #   define __NODE_ALLOCATOR_LOCK 
  61.         if (threads) pthread_mutex_lock(&_S_node_allocator_lock)
  62. #   define __NODE_ALLOCATOR_UNLOCK 
  63.         if (threads) pthread_mutex_unlock(&_S_node_allocator_lock)
  64. #   define __NODE_ALLOCATOR_THREADS true
  65. #   define __VOLATILE volatile  // Needed at -O3 on SGI
  66. # endif
  67. # ifdef __STL_WIN32THREADS
  68.     // The lock needs to be initialized by constructing an allocator
  69.     // objects of the right type.  We do that here explicitly for alloc.
  70. #   define __NODE_ALLOCATOR_LOCK 
  71.         EnterCriticalSection(&_S_node_allocator_lock)
  72. #   define __NODE_ALLOCATOR_UNLOCK 
  73.         LeaveCriticalSection(&_S_node_allocator_lock)
  74. #   define __NODE_ALLOCATOR_THREADS true
  75. #   define __VOLATILE volatile  // may not be needed
  76. # endif /* WIN32THREADS */
  77. # ifdef __STL_SGI_THREADS
  78.     // This should work without threads, with sproc threads, or with
  79.     // pthreads.  It is suboptimal in all cases.
  80.     // It is unlikely to even compile on nonSGI machines.
  81.     extern "C" {
  82.       extern int __us_rsthread_malloc;
  83.     }
  84. // The above is copied from malloc.h.  Including <malloc.h>
  85. // would be cleaner but fails with certain levels of standard
  86. // conformance.
  87. #   define __NODE_ALLOCATOR_LOCK if (threads && __us_rsthread_malloc) 
  88.                 { _S_lock(&_S_node_allocator_lock); }
  89. #   define __NODE_ALLOCATOR_UNLOCK if (threads && __us_rsthread_malloc) 
  90.                 { _S_unlock(&_S_node_allocator_lock); }
  91. #   define __NODE_ALLOCATOR_THREADS true
  92. #   define __VOLATILE volatile  // Needed at -O3 on SGI
  93. # endif
  94. # ifdef _NOTHREADS
  95. //  Thread-unsafe
  96. #   define __NODE_ALLOCATOR_LOCK
  97. #   define __NODE_ALLOCATOR_UNLOCK
  98. #   define __NODE_ALLOCATOR_THREADS false
  99. #   define __VOLATILE
  100. # endif
  101. __STL_BEGIN_NAMESPACE
  102. #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
  103. #pragma set woff 1174
  104. #endif
  105. // Malloc-based allocator.  Typically slower than default alloc below.
  106. // Typically thread-safe and more storage efficient.
  107. #ifdef __STL_STATIC_TEMPLATE_MEMBER_BUG
  108. # ifdef __DECLARE_GLOBALS_HERE
  109.     void (* __malloc_alloc_oom_handler)() = 0;
  110.     // g++ 2.7.2 does not handle static template data members.
  111. # else
  112.     extern void (* __malloc_alloc_oom_handler)();
  113. # endif
  114. #endif
  115. template <int __inst>
  116. class __malloc_alloc_template {
  117. private:
  118.   static void* _S_oom_malloc(size_t);
  119.   static void* _S_oom_realloc(void*, size_t);
  120. #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
  121.   static void (* __malloc_alloc_oom_handler)();
  122. #endif
  123. public:
  124.   static void* allocate(size_t __n)
  125.   {
  126.     void* __result = malloc(__n);
  127.     if (0 == __result) __result = _S_oom_malloc(__n);
  128.     return __result;
  129.   }
  130.   static void deallocate(void* __p, size_t /* __n */)
  131.   {
  132.     free(__p);
  133.   }
  134.   static void* reallocate(void* __p, size_t /* old_sz */, size_t __new_sz)
  135.   {
  136.     void* __result = realloc(__p, __new_sz);
  137.     if (0 == __result) __result = _S_oom_realloc(__p, __new_sz);
  138.     return __result;
  139.   }
  140.   static void (* __set_malloc_handler(void (*__f)()))()
  141.   {
  142.     void (* __old)() = __malloc_alloc_oom_handler;
  143.     __malloc_alloc_oom_handler = __f;
  144.     return(__old);
  145.   }
  146. };
  147. // malloc_alloc out-of-memory handling
  148. #ifndef __STL_STATIC_TEMPLATE_MEMBER_BUG
  149. template <int __inst>
  150. void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0;
  151. #endif
  152. template <int __inst>
  153. void*
  154. __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
  155. {
  156.     void (* __my_malloc_handler)();
  157.     void* __result;
  158.     for (;;) {
  159.         __my_malloc_handler = __malloc_alloc_oom_handler;
  160.         if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; }
  161.         (*__my_malloc_handler)();
  162.         __result = malloc(__n);
  163.         if (__result) return(__result);
  164.     }
  165. }
  166. template <int __inst>
  167. void* __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n)
  168. {
  169.     void (* __my_malloc_handler)();
  170.     void* __result;
  171.     for (;;) {
  172.         __my_malloc_handler = __malloc_alloc_oom_handler;
  173.         if (0 == __my_malloc_handler) { __THROW_BAD_ALLOC; }
  174.         (*__my_malloc_handler)();
  175.         __result = realloc(__p, __n);
  176.         if (__result) return(__result);
  177.     }
  178. }
  179. typedef __malloc_alloc_template<0> malloc_alloc;
  180. template<class _T, class _Alloc>
  181. class simple_alloc {
  182. public:
  183.     static _T* allocate(size_t __n)
  184.       { return 0 == __n ? 0 : (_T*) _Alloc::allocate(__n * sizeof (_T)); }
  185.     static _T* allocate(void)
  186.       { return (_T*) _Alloc::allocate(sizeof (_T)); }
  187.     static void deallocate(_T* __p, size_t __n)
  188.       { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_T)); }
  189.     static void deallocate(_T* __p)
  190.       { _Alloc::deallocate(__p, sizeof (_T)); }
  191. };
  192. // Allocator adaptor to check size arguments for debugging.
  193. // Reports errors using assert.  Checking can be disabled with
  194. // NDEBUG, but it's far better to just use the underlying allocator
  195. // instead when no checking is desired.
  196. // There is some evidence that this can confuse Purify.
  197. template <class _Alloc>
  198. class debug_alloc {
  199. private:
  200.   enum {_S_extra = 8};  // Size of space used to store size.  Note
  201.                         // that this must be large enough to preserve
  202.                         // alignment.
  203. public:
  204.   static void* allocate(size_t __n)
  205.   {
  206.     char* __result = (char*)_Alloc::allocate(__n + _S_extra);
  207.     *(size_t*)__result = __n;
  208.     return __result + _S_extra;
  209.   }
  210.   static void deallocate(void* __p, size_t __n)
  211.   {
  212.     char* __real_p = (char*)__p - _S_extra;
  213.     assert(*(size_t*)__real_p == __n);
  214.     _Alloc::deallocate(__real_p, __n + _S_extra);
  215.   }
  216.   static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz)
  217.   {
  218.     char* __real_p = (char*)__p - _S_extra;
  219.     assert(*(size_t*)__real_p == __old_sz);
  220.     char* __result = (char*)
  221.       _Alloc::reallocate(__real_p, __old_sz + _S_extra, __new_sz + _S_extra);
  222.     *(size_t*)__result = __new_sz;
  223.     return __result + _S_extra;
  224.   }
  225. };
  226. # ifdef __USE_MALLOC
  227. typedef malloc_alloc alloc;
  228. typedef malloc_alloc single_client_alloc;
  229. # else
  230. // Default node allocator.
  231. // With a reasonable compiler, this should be roughly as fast as the
  232. // original STL class-specific allocators, but with less fragmentation.
  233. // Default_alloc_template parameters are experimental and MAY
  234. // DISAPPEAR in the future.  Clients should just use alloc for now.
  235. //
  236. // Important implementation properties:
  237. // 1. If the client request an object of size > _MAX_BYTES, the resulting
  238. //    object will be obtained directly from malloc.
  239. // 2. In all other cases, we allocate an object of size exactly
  240. //    _S_round_up(requested_size).  Thus the client has enough size
  241. //    information that we can return the object to the proper free list
  242. //    without permanently losing part of the object.
  243. //
  244. // The first template parameter specifies whether more than one thread
  245. // may use this allocator.  It is safe to allocate an object from
  246. // one instance of a default_alloc and deallocate it with another
  247. // one.  This effectively transfers its ownership to the second one.
  248. // This may have undesirable effects on reference locality.
  249. // The second parameter is unreferenced and serves only to allow the
  250. // creation of multiple default_alloc instances.
  251. // Node that containers built on different allocator instances have
  252. // different types, limiting the utility of this approach.
  253. #ifdef __SUNPRO_CC
  254. // breaks if we make these template class members:
  255.   enum {_ALIGN = 8};
  256.   enum {_MAX_BYTES = 128};
  257.   enum {_NFREELISTS = _MAX_BYTES/_ALIGN};
  258. #endif
  259. template <bool threads, int inst>
  260. class __default_alloc_template {
  261. private:
  262.   // Really we should use static const int x = N
  263.   // instead of enum { x = N }, but few compilers accept the former.
  264. # ifndef __SUNPRO_CC
  265.     enum {_ALIGN = 8};
  266.     enum {_MAX_BYTES = 128};
  267.     enum {_NFREELISTS = _MAX_BYTES/_ALIGN};
  268. # endif
  269.   static size_t
  270.   _S_round_up(size_t __bytes) 
  271.     { return (((__bytes) + _ALIGN-1) & ~(_ALIGN - 1)); }
  272. __PRIVATE:
  273.   union _Obj {
  274.         union _Obj* _M_free_list_link;
  275.         char _M_client_data[1];    /* The client sees this.        */
  276.   };
  277. private:
  278. # ifdef __SUNPRO_CC
  279.     static _Obj* __VOLATILE _S_free_list[]; 
  280.         // Specifying a size results in duplicate def for 4.1
  281. # else
  282.     static _Obj* __VOLATILE _S_free_list[_NFREELISTS]; 
  283. # endif
  284.   static  size_t _S_freelist_index(size_t __bytes) {
  285.         return (((__bytes) + _ALIGN-1)/_ALIGN - 1);
  286.   }
  287.   // Returns an object of size __n, and optionally adds to size __n free list.
  288.   static void* _S_refill(size_t __n);
  289.   // Allocates a chunk for nobjs of size size.  nobjs may be reduced
  290.   // if it is inconvenient to allocate the requested number.
  291.   static char* _S_chunk_alloc(size_t __size, int& __nobjs);
  292.   // Chunk allocation state.
  293.   static char* _S_start_free;
  294.   static char* _S_end_free;
  295.   static size_t _S_heap_size;
  296. # ifdef __STL_SGI_THREADS
  297.     static volatile unsigned long _S_node_allocator_lock;
  298.     static void _S_lock(volatile unsigned long*); 
  299.     static inline void _S_unlock(volatile unsigned long*);
  300. # endif
  301. # ifdef _PTHREADS
  302.     static pthread_mutex_t _S_node_allocator_lock;
  303. # endif
  304. # ifdef __STL_WIN32THREADS
  305.     static CRITICAL_SECTION _S_node_allocator_lock;
  306.     static bool _S_node_allocator_lock_initialized;
  307.   public:
  308.     __default_alloc_template() {
  309. // This assumes the first constructor is called before threads
  310. // are started.
  311.         if (!_S_node_allocator_lock_initialized) {
  312.             InitializeCriticalSection(&_S_node_allocator_lock);
  313.             _S_node_allocator_lock_initialized = true;
  314.         }
  315.     }
  316.   private:
  317. # endif
  318.     class _Lock {
  319.         public:
  320.             _Lock() { __NODE_ALLOCATOR_LOCK; }
  321.             ~_Lock() { __NODE_ALLOCATOR_UNLOCK; }
  322.     };
  323.     friend class _Lock;
  324. public:
  325.   /* __n must be > 0      */
  326.   static void* allocate(size_t __n)
  327.   {
  328.     _Obj* __VOLATILE* __my_free_list;
  329.     _Obj* __RESTRICT __result;
  330.     if (__n > (size_t) _MAX_BYTES) {
  331.         return(malloc_alloc::allocate(__n));
  332.     }
  333.     __my_free_list = _S_free_list + _S_freelist_index(__n);
  334.     // Acquire the lock here with a constructor call.
  335.     // This ensures that it is released in exit or during stack
  336.     // unwinding.
  337. #       ifndef _NOTHREADS
  338.         /*REFERENCED*/
  339.         _Lock __lock_instance;
  340. #       endif
  341.     __result = *__my_free_list;
  342.     if (__result == 0) {
  343.         void* __r = _S_refill(_S_round_up(__n));
  344.         return __r;
  345.     }
  346.     *__my_free_list = __result -> _M_free_list_link;
  347.     return (__result);
  348.   };
  349.   /* __p may not be 0 */
  350.   static void deallocate(void* __p, size_t __n)
  351.   {
  352.     _Obj* __q = (_Obj*)__p;
  353.     _Obj* __VOLATILE* __my_free_list;
  354.     if (__n > (size_t) _MAX_BYTES) {
  355.         malloc_alloc::deallocate(__p, __n);
  356.         return;
  357.     }
  358.     __my_free_list = _S_free_list + _S_freelist_index(__n);
  359.     // acquire lock
  360. #       ifndef _NOTHREADS
  361.         /*REFERENCED*/
  362.         _Lock __lock_instance;
  363. #       endif /* _NOTHREADS */
  364.     __q -> _M_free_list_link = *__my_free_list;
  365.     *__my_free_list = __q;
  366.     // lock is released here
  367.   }
  368.   static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz);
  369. } ;
  370. typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
  371. typedef __default_alloc_template<false, 0> single_client_alloc;
  372. /* We allocate memory in large chunks in order to avoid fragmenting     */
  373. /* the malloc heap too much.                                            */
  374. /* We assume that size is properly aligned.                             */
  375. /* We hold the allocation lock.                                         */
  376. template <bool __threads, int __inst>
  377. char*
  378. __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size, 
  379.                                                             int& __nobjs)
  380. {
  381.     char* __result;
  382.     size_t __total_bytes = __size * __nobjs;
  383.     size_t __bytes_left = _S_end_free - _S_start_free;
  384.     if (__bytes_left >= __total_bytes) {
  385.         __result = _S_start_free;
  386.         _S_start_free += __total_bytes;
  387.         return(__result);
  388.     } else if (__bytes_left >= __size) {
  389.         __nobjs = (int)(__bytes_left/__size);
  390.         __total_bytes = __size * __nobjs;
  391.         __result = _S_start_free;
  392.         _S_start_free += __total_bytes;
  393.         return(__result);
  394.     } else {
  395.         size_t __bytes_to_get = 
  396.   2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
  397.         // Try to make use of the left-over piece.
  398.         if (__bytes_left > 0) {
  399.             _Obj* __VOLATILE* __my_free_list =
  400.                         _S_free_list + _S_freelist_index(__bytes_left);
  401.             ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
  402.             *__my_free_list = (_Obj*)_S_start_free;
  403.         }
  404.         _S_start_free = (char*)malloc(__bytes_to_get);
  405.         if (0 == _S_start_free) {
  406.             size_t __i;
  407.             _Obj* __VOLATILE* __my_free_list;
  408.     _Obj* __p;
  409.             // Try to make do with what we have.  That can't
  410.             // hurt.  We do not try smaller requests, since that tends
  411.             // to result in disaster on multi-process machines.
  412.             for (__i = __size; __i <= _MAX_BYTES; __i += _ALIGN) {
  413.                 __my_free_list = _S_free_list + _S_freelist_index(__i);
  414.                 __p = *__my_free_list;
  415.                 if (0 != __p) {
  416.                     *__my_free_list = __p -> _M_free_list_link;
  417.                     _S_start_free = (char*)__p;
  418.                     _S_end_free = _S_start_free + __i;
  419.                     return(_S_chunk_alloc(__size, __nobjs));
  420.                     // Any leftover piece will eventually make it to the
  421.                     // right free list.
  422.                 }
  423.             }
  424.     _S_end_free = 0; // In case of exception.
  425.             _S_start_free = (char*)malloc_alloc::allocate(__bytes_to_get);
  426.             // This should either throw an
  427.             // exception or remedy the situation.  Thus we assume it
  428.             // succeeded.
  429.         }
  430.         _S_heap_size += __bytes_to_get;
  431.         _S_end_free = _S_start_free + __bytes_to_get;
  432.         return(_S_chunk_alloc(__size, __nobjs));
  433.     }
  434. }
  435. /* Returns an object of size __n, and optionally adds to size __n free list.*/
  436. /* We assume that __n is properly aligned.                                */
  437. /* We hold the allocation lock.                                         */
  438. template <bool __threads, int __inst>
  439. void*
  440. __default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
  441. {
  442.     int __nobjs = 20;
  443.     char* __chunk = _S_chunk_alloc(__n, __nobjs);
  444.     _Obj* __VOLATILE* __my_free_list;
  445.     _Obj* __result;
  446.     _Obj* __current_obj;
  447.     _Obj* __next_obj;
  448.     int __i;
  449.     if (1 == __nobjs) return(__chunk);
  450.     __my_free_list = _S_free_list + _S_freelist_index(__n);
  451.     /* Build free list in chunk */
  452.       __result = (_Obj*)__chunk;
  453.       *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
  454.       for (__i = 1; ; __i++) {
  455.         __current_obj = __next_obj;
  456.         __next_obj = (_Obj*)((char*)__next_obj + __n);
  457.         if (__nobjs - 1 == __i) {
  458.             __current_obj -> _M_free_list_link = 0;
  459.             break;
  460.         } else {
  461.             __current_obj -> _M_free_list_link = __next_obj;
  462.         }
  463.       }
  464.     return(__result);
  465. }
  466. template <bool threads, int inst>
  467. void*
  468. __default_alloc_template<threads, inst>::reallocate(void* __p,
  469.                                                     size_t __old_sz,
  470.                                                     size_t __new_sz)
  471. {
  472.     void* __result;
  473.     size_t __copy_sz;
  474.     if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) {
  475.         return(realloc(__p, __new_sz));
  476.     }
  477.     if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p);
  478.     __result = allocate(__new_sz);
  479.     __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
  480.     memcpy(__result, __p, __copy_sz);
  481.     deallocate(__p, __old_sz);
  482.     return(__result);
  483. }
  484. #ifdef _PTHREADS
  485.     template <bool __threads, int __inst>
  486.     pthread_mutex_t
  487.     __default_alloc_template<__threads, __inst>::_S_node_allocator_lock
  488.         = PTHREAD_MUTEX_INITIALIZER;
  489. #endif
  490. #ifdef __STL_WIN32THREADS
  491.     template <bool __threads, int __inst>
  492.     CRITICAL_SECTION
  493.     __default_alloc_template<__threads, __inst>::
  494.       _S_node_allocator_lock;
  495.     template <bool __threads, int __inst>
  496.     bool
  497.     __default_alloc_template<__threads, __inst>::
  498.       _S_node_allocator_lock_initialized
  499. = false;
  500. #endif
  501. #ifdef __STL_SGI_THREADS
  502. __STL_END_NAMESPACE
  503. #include <mutex.h>
  504. #include <time.h>  /* XXX should use <ctime> */
  505. __STL_BEGIN_NAMESPACE
  506. // Somewhat generic lock implementations.  We need only test-and-set
  507. // and some way to sleep.  These should work with both SGI pthreads
  508. // and sproc threads.  They may be useful on other systems.
  509. template <bool __threads, int __inst>
  510. volatile unsigned long
  511. __default_alloc_template<__threads, __inst>::_S_node_allocator_lock = 0;
  512. #if __mips < 3 || !(defined (_ABIN32) || defined(_ABI64)) || defined(__GNUC__)
  513. #   define __test_and_set(l,v) test_and_set(l,v)
  514. #endif
  515. template <bool __threads, int __inst>
  516. void 
  517. __default_alloc_template<__threads, __inst>::
  518.   _S_lock(volatile unsigned long* __lock)
  519. {
  520.     const unsigned __low_spin_max = 30;  // spins if we suspect uniprocessor
  521.     const unsigned __high_spin_max = 1000; // spins for multiprocessor
  522.     static unsigned __spin_max = __low_spin_max;
  523.     unsigned __my_spin_max;
  524.     static unsigned __last_spins = 0;
  525.     unsigned __my_last_spins;
  526.     unsigned __junk;
  527. #   define __ALLOC_PAUSE 
  528.       __junk *= __junk; __junk *= __junk; __junk *= __junk; __junk *= __junk
  529.     int __i;
  530.     if (!__test_and_set((unsigned long*)__lock, 1)) {
  531.         return;
  532.     }
  533.     __my_spin_max = __spin_max;
  534.     __my_last_spins = __last_spins;
  535.     for (__i = 0; __i < __my_spin_max; __i++) {
  536.         if (__i < __my_last_spins/2 || *__lock) {
  537.             __ALLOC_PAUSE;
  538.             continue;
  539.         }
  540.         if (!__test_and_set((unsigned long*)__lock, 1)) {
  541.             // got it!
  542.             // Spinning worked.  Thus we're probably not being scheduled
  543.             // against the other process with which we were contending.
  544.             // Thus it makes sense to spin longer the next time.
  545.             __last_spins = __i;
  546.             __spin_max = __high_spin_max;
  547.             return;
  548.         }
  549.     }
  550.     // We are probably being scheduled against the other process.  Sleep.
  551.     __spin_max = __low_spin_max;
  552.     for (__i = 0 ;; ++__i) {
  553.         struct timespec __ts;
  554.         int __log_nsec = __i + 6;
  555.         if (!__test_and_set((unsigned long *)__lock, 1)) {
  556.             return;
  557.         }
  558.         if (__log_nsec > 27) __log_nsec = 27;
  559. /* Max sleep is 2**27nsec ~ 60msec      */
  560.         __ts.tv_sec = 0;
  561.         __ts.tv_nsec = 1 << __log_nsec;
  562.         nanosleep(&__ts, 0);
  563.     }
  564. }
  565. template <bool __threads, int __inst>
  566. inline void
  567. __default_alloc_template<__threads, __inst>::_S_unlock(
  568.   volatile unsigned long* __lock)
  569. {
  570. #   if defined(__GNUC__) && __mips >= 3
  571.         asm("sync");
  572.         *__lock = 0;
  573. #   elif __mips >= 3 && (defined (_ABIN32) || defined(_ABI64))
  574.         __lock_release(__lock);
  575. #   else 
  576.         *__lock = 0;
  577.         // This is not sufficient on many multiprocessors, since
  578.         // writes to protected variables and the lock may be reordered.
  579. #   endif
  580. }
  581. #endif
  582. template <bool __threads, int __inst>
  583. char* __default_alloc_template<__threads, __inst>::_S_start_free = 0;
  584. template <bool __threads, int __inst>
  585. char* __default_alloc_template<__threads, __inst>::_S_end_free = 0;
  586. template <bool __threads, int __inst>
  587. size_t __default_alloc_template<__threads, __inst>::_S_heap_size = 0;
  588. template <bool __threads, int __inst>
  589. __default_alloc_template<__threads, __inst>::_Obj* __VOLATILE
  590. __default_alloc_template<__threads, __inst> ::_S_free_list[
  591. # ifdef __SUNPRO_CC
  592.     _NFREELISTS
  593. # else
  594.     __default_alloc_template<__threads, __inst>::_NFREELISTS
  595. # endif
  596. ] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
  597. // The 16 zeros are necessary to make version 4.1 of the SunPro
  598. // compiler happy.  Otherwise it appears to allocate too little
  599. // space for the array.
  600. # ifdef __STL_WIN32THREADS
  601.   // Create one to get critical section initialized.
  602.   // We do this onece per file, but only the first constructor
  603.   // does anything.
  604.   static alloc __node_allocator_dummy_instance;
  605. # endif
  606. #endif /* ! __USE_MALLOC */
  607. // This implements allocators as specified in the C++ standard.  
  608. //
  609. // Note that standard-conforming allocators use many language features
  610. // that are not yet widely implemented.  In particular, they rely on
  611. // member templates, partial specialization, partial ordering of function
  612. // templates, the typename keyword, and the use of the template keyword
  613. // to refer to a template member of a dependent type.
  614. #ifdef __STL_USE_STD_ALLOCATORS
  615. template <class _T>
  616. class allocator {
  617.   typedef alloc _Alloc;          // The underlying allocator.
  618. public:
  619.   typedef size_t    size_type;
  620.   typedef ptrdiff_t difference_type;
  621.   typedef _T*       pointer;
  622.   typedef const _T* const_pointer;
  623.   typedef _T&       reference;
  624.   typedef const _T& const_reference;
  625.   typedef _T        value_type;
  626.   template <class _T1> struct rebind {
  627.     typedef allocator<_T1> other;
  628.   };
  629.   allocator() __STL_NOTHROW {}
  630.   allocator(const allocator&) __STL_NOTHROW {}
  631.   template <class _T1> allocator(const allocator<_T1>&) __STL_NOTHROW {}
  632.   ~allocator() __STL_NOTHROW {}
  633.   pointer address(reference __x) const { return &__x; }
  634.   const_pointer address(const_reference __x) const { return &__x; }
  635.   // __n is permitted to be 0.  The C++ standard says nothing about what
  636.   // the return value is when __n == 0.
  637.   _T* allocate(size_type __n, const void* = 0) {
  638.     return __n != 0 ? static_cast<_T*>(_Alloc::allocate(__n * sizeof(_T))) 
  639.                     : 0;
  640.   }
  641.   // __p is not permitted to be a null pointer.
  642.   void deallocate(pointer __p, size_type __n)
  643.     { _Alloc::deallocate(__p, __n * sizeof(_T)); }
  644.   size_type max_size() const __STL_NOTHROW 
  645.     { return size_t(-1) / sizeof(_T); }
  646.   void construct(pointer __p, const _T& __val) { new(__p) _T(__val); }
  647.   void destroy(pointer __p) { __p->~_T(); }
  648. };
  649. template<>
  650. class allocator<void> {
  651.   typedef size_t      size_type;
  652.   typedef ptrdiff_t   difference_type;
  653.   typedef void*       pointer;
  654.   typedef const void* const_pointer;
  655.   typedef void        value_type;
  656.   template <class _T1> struct rebind {
  657.     typedef allocator<_T1> other;
  658.   };
  659. };
  660. template <class T1, class T2>
  661. inline bool operator==(const allocator<T1>& __a1,
  662.                        const allocator<T2>& __a2) 
  663. {
  664.   return true;
  665. }
  666. template <class T1, class T2>
  667. inline bool operator!=(const allocator<T1>& __a1,
  668.                        const allocator<T2>& __a2)
  669. {
  670.   return false;
  671. }
  672. // Allocator adaptor to turn an SGI-style allocator (e.g. alloc, malloc_alloc)
  673. // into a standard-conforming allocator.   Note that this adaptor does
  674. // *not* assume that all objects of the underlying alloc class are
  675. // identical, nor does it assume that all of the underlying alloc's
  676. // member functions are static member functions.  Note, also, that 
  677. // __allocator<_T, alloc> is essentially the same thing as allocator<_T>.
  678. template <class _T, class _Alloc>
  679. struct __allocator {
  680.   _Alloc __underlying_alloc;
  681.   typedef size_t    size_type;
  682.   typedef ptrdiff_t difference_type;
  683.   typedef _T*       pointer;
  684.   typedef const _T* const_pointer;
  685.   typedef _T&       reference;
  686.   typedef const _T& const_reference;
  687.   typedef _T        value_type;
  688.   template <class _T1> struct rebind {
  689.     typedef __allocator<_T1, _Alloc> other;
  690.   };
  691.   __allocator() __STL_NOTHROW {}
  692.   __allocator(const __allocator& __a) __STL_NOTHROW
  693.     : __underlying_alloc(__a.__underlying_alloc) {}
  694.   template <class _T1> 
  695.   __allocator(const __allocator<_T1, _Alloc>& __a) __STL_NOTHROW
  696.     : __underlying_alloc(__a.__underlying_alloc) {}
  697.   ~__allocator() __STL_NOTHROW {}
  698.   pointer address(reference __x) const { return &__x; }
  699.   const_pointer address(const_reference __x) const { return &__x; }
  700.   // __n is permitted to be 0.
  701.   _T* allocate(size_type __n, const void* = 0) {
  702.     return __n != 0 
  703.         ? static_cast<_T*>(__underlying_alloc.allocate(__n * sizeof(_T))) 
  704.         : 0;
  705.   }
  706.   // __p is not permitted to be a null pointer.
  707.   void deallocate(pointer __p, size_type __n)
  708.     { __underlying_alloc.deallocate(__p, __n * sizeof(_T)); }
  709.   size_type max_size() const __STL_NOTHROW 
  710.     { return size_t(-1) / sizeof(_T); }
  711.   void construct(pointer __p, const _T& __val) { new(__p) _T(__val); }
  712.   void destroy(pointer __p) { __p->~_T(); }
  713. };
  714. template <class _Alloc>
  715. class __allocator<void, _Alloc> {
  716.   typedef size_t      size_type;
  717.   typedef ptrdiff_t   difference_type;
  718.   typedef void*       pointer;
  719.   typedef const void* const_pointer;
  720.   typedef void        value_type;
  721.   template <class _T1> struct rebind {
  722.     typedef __allocator<_T1, _Alloc> other;
  723.   };
  724. };
  725. template <class _T, class _Alloc>
  726. inline bool operator==(const __allocator<_T, _Alloc>& __a1,
  727.                        const __allocator<_T, _Alloc>& __a2)
  728. {
  729.   return __a1.__underlying_alloc == __a2.__underlying_alloc;
  730. }
  731. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  732. template <class _T, class _Alloc>
  733. inline bool operator!=(const __allocator<_T, _Alloc>& __a1,
  734.                        const __allocator<_T, _Alloc>& __a2)
  735. {
  736.   return __a1.__underlying_alloc != __a2.__underlying_alloc;
  737. }
  738. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  739. // Comparison operators for all of the predifined SGI-style allocators.
  740. // This ensures that __allocator<malloc_alloc> (for example) will
  741. // work correctly.
  742. template <int inst>
  743. inline bool operator==(const __malloc_alloc_template<inst>&,
  744.                        const __malloc_alloc_template<inst>&)
  745. {
  746.   return true;
  747. }
  748. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  749. template <int __inst>
  750. inline bool operator!=(const __malloc_alloc_template<__inst>&,
  751.                        const __malloc_alloc_template<__inst>&)
  752. {
  753.   return false;
  754. }
  755. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  756. template <bool __threads, int __inst>
  757. inline bool operator==(const __default_alloc_template<__threads, __inst>&,
  758.                        const __default_alloc_template<__threads, __inst>&)
  759. {
  760.   return true;
  761. }
  762. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  763. template <bool __threads, int __inst>
  764. inline bool operator!=(const __default_alloc_template<__threads, __inst>&,
  765.                        const __default_alloc_template<__threads, __inst>&)
  766. {
  767.   return false;
  768. }
  769. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  770. template <class _Alloc>
  771. inline bool operator==(const debug_alloc<_Alloc>&,
  772.                        const debug_alloc<_Alloc>&) {
  773.   return true;
  774. }
  775. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  776. template <class _Alloc>
  777. inline bool operator!=(const debug_alloc<_Alloc>&,
  778.                        const debug_alloc<_Alloc>&) {
  779.   return false;
  780. }
  781. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  782. // Another allocator adaptor: _Alloc_traits.  This serves two
  783. // purposes.  First, make it possible to write containers that can use
  784. // either SGI-style allocators or standard-conforming allocator.
  785. // Second, provide a mechanism so that containers can query whether or
  786. // not the allocator has distinct instances.  If not, the container
  787. // can avoid wasting a word of memory to store an empty object.
  788. // This adaptor uses partial specialization.  The general case of
  789. // _Alloc_traits<_T, _Alloc> assumes that _Alloc is a
  790. // standard-conforming allocator, possibly with non-equal instances
  791. // and non-static members.  (It still behaves correctly even if _Alloc
  792. // has static member and if all instances are equal.  Refinements
  793. // affect performance, not correctness.)
  794. // There are always two members: allocator_type, which is a standard-
  795. // conforming allocator type for allocating objects of type _T, and
  796. // _S_instanceless, a static const member of type bool.  If
  797. // _S_instanceless is true, this means that there is no difference
  798. // between any two instances of type allocator_type.  Furthermore, if
  799. // _S_instanceless is true, then _Alloc_traits has one additional
  800. // member: _Alloc_type.  This type encapsulates allocation and
  801. // deallocation of objects of type _T through a static interface; it
  802. // has two member functions, whose signatures are
  803. //    static _T* allocate(size_t)
  804. //    static void deallocate(_T*, size_t)
  805. // The fully general version.
  806. template <class _T, class _Allocator>
  807. struct _Alloc_traits
  808. {
  809.   static const bool _S_instanceless = false;
  810.   typedef typename _Allocator::__STL_TEMPLATE rebind<_T>::other 
  811.           allocator_type;
  812. };
  813. template <class _T, class _Allocator>
  814. const bool _Alloc_traits<_T, _Allocator>::_S_instanceless;
  815. // The version for the default allocator.
  816. template <class _T, class _T1>
  817. struct _Alloc_traits<_T, allocator<_T1> >
  818. {
  819.   static const bool _S_instanceless = true;
  820.   typedef simple_alloc<_T, alloc> _Alloc_type;
  821.   typedef allocator<_T> allocator_type;
  822. };
  823. // Versions for the predefined SGI-style allocators.
  824. template <class _T, int __inst>
  825. struct _Alloc_traits<_T, __malloc_alloc_template<__inst> >
  826. {
  827.   static const bool _S_instanceless = true;
  828.   typedef simple_alloc<_T, __malloc_alloc_template<__inst> > _Alloc_type;
  829.   typedef __allocator<_T, __malloc_alloc_template<__inst> > allocator_type;
  830. };
  831. template <class _T, bool __threads, int __inst>
  832. struct _Alloc_traits<_T, __default_alloc_template<__threads, __inst> >
  833. {
  834.   static const bool _S_instanceless = true;
  835.   typedef simple_alloc<_T, __default_alloc_template<__threads, __inst> > 
  836.           _Alloc_type;
  837.   typedef __allocator<_T, __default_alloc_template<__threads, __inst> > 
  838.           allocator_type;
  839. };
  840. template <class _T, class _Alloc>
  841. struct _Alloc_traits<_T, debug_alloc<_Alloc> >
  842. {
  843.   static const bool _S_instanceless = true;
  844.   typedef simple_alloc<_T, debug_alloc<_Alloc> > _Alloc_type;
  845.   typedef __allocator<_T, debug_alloc<_Alloc> > allocator_type;
  846. };
  847. // Versions for the __allocator adaptor used with the predefined
  848. // SGI-style allocators.
  849. template <class _T, class _T1, int __inst>
  850. struct _Alloc_traits<_T, __allocator<_T1, __malloc_alloc_template<__inst> > >
  851. {
  852.   static const bool _S_instanceless = true;
  853.   typedef simple_alloc<_T, __malloc_alloc_template<__inst> > _Alloc_type;
  854.   typedef __allocator<_T, __malloc_alloc_template<__inst> > allocator_type;
  855. };
  856. template <class _T, class _T1, bool __thr, int __inst>
  857. struct _Alloc_traits<_T, 
  858.                       __allocator<_T1, 
  859.                                   __default_alloc_template<__thr, __inst> > >
  860. {
  861.   static const bool _S_instanceless = true;
  862.   typedef simple_alloc<_T, __default_alloc_template<__thr,__inst> > 
  863.           _Alloc_type;
  864.   typedef __allocator<_T, __default_alloc_template<__thr,__inst> > 
  865.           allocator_type;
  866. };
  867. template <class _T, class _T1, class _Alloc>
  868. struct _Alloc_traits<_T, __allocator<_T1, debug_alloc<_Alloc> > >
  869. {
  870.   static const bool _S_instanceless = true;
  871.   typedef simple_alloc<_T, debug_alloc<_Alloc> > _Alloc_type;
  872.   typedef __allocator<_T, debug_alloc<_Alloc> > allocator_type;
  873. };
  874. #endif /* __STL_USE_STD_ALLOCATORS */
  875. #if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
  876. #pragma reset woff 1174
  877. #endif
  878. __STL_END_NAMESPACE
  879. #undef __PRIVATE
  880. #endif /* __SGI_STL_INTERNAL_ALLOC_H */
  881. // Local Variables:
  882. // mode:C++
  883. // End: