00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef _STLP_PTHREAD_ALLOC_H
00027 #define _STLP_PTHREAD_ALLOC_H
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifndef _STLP_INTERNAL_ALLOC_H
00043 #include <stl/_alloc.h>
00044 #endif
00045
00046 #ifndef __RESTRICT
00047 # define __RESTRICT
00048 #endif
00049
00050 _STLP_BEGIN_NAMESPACE
00051
00052 #define _STLP_DATA_ALIGNMENT 8
00053
00054 union _Pthread_alloc_obj {
00055 union _Pthread_alloc_obj * __free_list_link;
00056 char __client_data[_STLP_DATA_ALIGNMENT];
00057 };
00058
00059
00060
00061
00062
00063
00064 template<size_t _Max_size>
00065 struct _Pthread_alloc_per_thread_state {
00066 typedef _Pthread_alloc_obj __obj;
00067 enum { _S_NFREELISTS = _Max_size/_STLP_DATA_ALIGNMENT };
00068 _Pthread_alloc_obj* volatile __free_list[_S_NFREELISTS];
00069 _Pthread_alloc_per_thread_state<_Max_size> * __next;
00070
00071
00072
00073
00074
00075 _Pthread_alloc_per_thread_state() : __next(0)
00076 {
00077 memset((void *)__free_list, 0, (size_t)_S_NFREELISTS * sizeof(__obj *));
00078 }
00079
00080 void *_M_refill(size_t __n);
00081 };
00082
00083
00084
00085
00086
00087 template < __DFL_NON_TYPE_PARAM(size_t, _Max_size, _MAX_BYTES) >
00088 class _Pthread_alloc {
00089
00090 public:
00091
00092 typedef _Pthread_alloc_obj __obj;
00093
00094
00095
00096 static char *_S_chunk_alloc(size_t __size, int &__nobjs);
00097
00098 enum {_S_ALIGN = _STLP_DATA_ALIGNMENT};
00099
00100 static size_t _S_round_up(size_t __bytes) {
00101 return (((__bytes) + (int)_S_ALIGN-1) & ~((int)_S_ALIGN - 1));
00102 }
00103 static size_t _S_freelist_index(size_t __bytes) {
00104 return (((__bytes) + (int)_S_ALIGN-1)/(int)_S_ALIGN - 1);
00105 }
00106
00107 private:
00108
00109
00110 static _STLP_mutex_base _S_chunk_allocator_lock;
00111 static char *_S_start_free;
00112 static char *_S_end_free;
00113 static size_t _S_heap_size;
00114 static _Pthread_alloc_per_thread_state<_Max_size>* _S_free_per_thread_states;
00115 static pthread_key_t _S_key;
00116 static bool _S_key_initialized;
00117
00118
00119 static void _S_destructor(void *instance);
00120
00121
00122 static _Pthread_alloc_per_thread_state<_Max_size> *_S_new_per_thread_state();
00123
00124 static _Pthread_alloc_per_thread_state<_Max_size> *_S_get_per_thread_state();
00125
00126
00127 class _M_lock;
00128 friend class _M_lock;
00129 class _M_lock {
00130 public:
00131 _M_lock () { _S_chunk_allocator_lock._M_acquire_lock(); }
00132 ~_M_lock () { _S_chunk_allocator_lock._M_release_lock(); }
00133 };
00134
00135 public:
00136
00137
00138 static void * allocate(size_t __n)
00139 {
00140 __obj * volatile * __my_free_list;
00141 __obj * __RESTRICT __result;
00142 _Pthread_alloc_per_thread_state<_Max_size>* __a;
00143
00144 if (__n > _Max_size) {
00145 return(__malloc_alloc<0>::allocate(__n));
00146 }
00147 if (!_S_key_initialized ||
00148 !(__a = (_Pthread_alloc_per_thread_state<_Max_size>*)
00149 pthread_getspecific(_S_key))) {
00150 __a = _S_get_per_thread_state();
00151 }
00152 __my_free_list = __a -> __free_list + _S_freelist_index(__n);
00153 __result = *__my_free_list;
00154 if (__result == 0) {
00155 void *__r = __a -> _M_refill(_S_round_up(__n));
00156 return __r;
00157 }
00158 *__my_free_list = __result -> __free_list_link;
00159 return (__result);
00160 };
00161
00162
00163 static void deallocate(void *__p, size_t __n)
00164 {
00165 __obj *__q = (__obj *)__p;
00166 __obj * volatile * __my_free_list;
00167 _Pthread_alloc_per_thread_state<_Max_size>* __a;
00168
00169 if (__n > _Max_size) {
00170 __malloc_alloc<0>::deallocate(__p, __n);
00171 return;
00172 }
00173 if (!_S_key_initialized ||
00174 !(__a = (_Pthread_alloc_per_thread_state<_Max_size> *)
00175 pthread_getspecific(_S_key))) {
00176 __a = _S_get_per_thread_state();
00177 }
00178 __my_free_list = __a->__free_list + _S_freelist_index(__n);
00179 __q -> __free_list_link = *__my_free_list;
00180 *__my_free_list = __q;
00181 }
00182
00183 static void * reallocate(void *__p, size_t __old_sz, size_t __new_sz);
00184
00185 } ;
00186
00187 # if defined (_STLP_USE_TEMPLATE_EXPORT)
00188 _STLP_EXPORT_TEMPLATE_CLASS _Pthread_alloc<_MAX_BYTES>;
00189 # endif
00190
00191 typedef _Pthread_alloc<_MAX_BYTES> __pthread_alloc;
00192 typedef __pthread_alloc pthread_alloc;
00193
00194 template <class _Tp>
00195 class pthread_allocator {
00196 typedef pthread_alloc _S_Alloc;
00197 public:
00198 typedef size_t size_type;
00199 typedef ptrdiff_t difference_type;
00200 typedef _Tp* pointer;
00201 typedef const _Tp* const_pointer;
00202 typedef _Tp& reference;
00203 typedef const _Tp& const_reference;
00204 typedef _Tp value_type;
00205
00206 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
00207 template <class _NewType> struct rebind {
00208 typedef pthread_allocator<_NewType> other;
00209 };
00210 #endif
00211
00212 pthread_allocator() _STLP_NOTHROW {}
00213 pthread_allocator(const pthread_allocator<_Tp>& a) _STLP_NOTHROW {}
00214
00215 #if defined (_STLP_MEMBER_TEMPLATES) && defined (_STLP_FUNCTION_PARTIAL_ORDER)
00216 template <class _OtherType> pthread_allocator(const pthread_allocator<_OtherType>&)
00217 _STLP_NOTHROW {}
00218 #endif
00219
00220 ~pthread_allocator() _STLP_NOTHROW {}
00221
00222 pointer address(reference __x) const { return &__x; }
00223 const_pointer address(const_reference __x) const { return &__x; }
00224
00225
00226
00227 _Tp* allocate(size_type __n, const void* = 0) {
00228 return __n != 0 ? __STATIC_CAST(_Tp*,_S_Alloc::allocate(__n * sizeof(_Tp)))
00229 : 0;
00230 }
00231
00232
00233 void deallocate(pointer __p, size_type __n)
00234 { _S_Alloc::deallocate(__p, __n * sizeof(_Tp)); }
00235
00236 size_type max_size() const _STLP_NOTHROW
00237 { return size_t(-1) / sizeof(_Tp); }
00238
00239 void construct(pointer __p, const _Tp& __val) { _STLP_PLACEMENT_NEW (__p) _Tp(__val); }
00240 void destroy(pointer _p) { _p->~_Tp(); }
00241 };
00242
00243 _STLP_TEMPLATE_NULL
00244 class _STLP_CLASS_DECLSPEC pthread_allocator<void> {
00245 public:
00246 typedef size_t size_type;
00247 typedef ptrdiff_t difference_type;
00248 typedef void* pointer;
00249 typedef const void* const_pointer;
00250 typedef void value_type;
00251 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
00252 template <class _NewType> struct rebind {
00253 typedef pthread_allocator<_NewType> other;
00254 };
00255 #endif
00256 };
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 template <class _T1, class _T2>
00268 inline bool operator==(const pthread_allocator<_T1>&,
00269 const pthread_allocator<_T2>& a2)
00270 {
00271 return true;
00272 }
00273
00274 #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER
00275 template <class _T1, class _T2>
00276 inline bool operator!=(const pthread_allocator<_T1>&,
00277 const pthread_allocator<_T2>&)
00278 {
00279 return false;
00280 }
00281 #endif
00282
00283 #ifdef _STLP_CLASS_PARTIAL_SPECIALIZATION
00284
00285 template <class _Tp, size_t _Max_size>
00286 struct _Alloc_traits<_Tp, _Pthread_alloc<_Max_size> >
00287 {
00288 typedef __allocator<_Tp, _Pthread_alloc<_Max_size> >
00289 allocator_type;
00290 };
00291
00292 template <class _Tp, class _Atype>
00293 struct _Alloc_traits<_Tp, pthread_allocator<_Atype> >
00294 {
00295 typedef pthread_allocator<_Tp> allocator_type;
00296 };
00297
00298 #endif
00299
00300 #if !defined (_STLP_MEMBER_TEMPLATE_CLASSES)
00301
00302 template <class _Tp1, class _Tp2>
00303 inline pthread_allocator<_Tp2>&
00304 __stl_alloc_rebind(pthread_allocator<_Tp1>& __x, const _Tp2*) {
00305 return (pthread_allocator<_Tp2>&)__x;
00306 }
00307
00308 template <class _Tp1, class _Tp2>
00309 inline pthread_allocator<_Tp2>
00310 __stl_alloc_create(pthread_allocator<_Tp1>&, const _Tp2*) {
00311 return pthread_allocator<_Tp2>();
00312 }
00313
00314 #endif
00315
00316 _STLP_END_NAMESPACE
00317
00318 # if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION) && !defined (_STLP_LINK_TIME_INSTANTIATION)
00319 # include <stl/_pthread_alloc.c>
00320 # endif
00321
00322 #endif
00323
00324
00325
00326